From 53a6f022b4fe8645468adaffca901dbf8c3c547e Mon Sep 17 00:00:00 2001 From: Jeremy Fertic Date: Tue, 11 Dec 2018 17:54:53 -0700 Subject: staging: iio: adt7316: fix register and bit definitions Change two register addresses and one bit definition to match the datasheet. Note that there are many issues in this driver so I would not suggest backporting these fixes to stable trees. Signed-off-by: Jeremy Fertic Fixes: 35f6b6b86ede ("staging: iio: new ADT7316/7/8 and ADT7516/7/9 driver") Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index dc93e85808e0..1fa4a4c2b4f3 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -59,8 +59,8 @@ #define ADT7316_CONFIG1 0x18 #define ADT7316_CONFIG2 0x19 #define ADT7316_CONFIG3 0x1A -#define ADT7316_LDAC_CONFIG 0x1B -#define ADT7316_DAC_CONFIG 0x1C +#define ADT7316_DAC_CONFIG 0x1B +#define ADT7316_LDAC_CONFIG 0x1C #define ADT7316_INT_MASK1 0x1D #define ADT7316_INT_MASK2 0x1E #define ADT7316_IN_TEMP_OFFSET 0x1F @@ -117,7 +117,7 @@ */ #define ADT7316_ADCLK_22_5 0x1 #define ADT7316_DA_HIGH_RESOLUTION 0x2 -#define ADT7316_DA_EN_VIA_DAC_LDCA 0x4 +#define ADT7316_DA_EN_VIA_DAC_LDCA 0x8 #define ADT7516_AIN_IN_VREF 0x10 #define ADT7316_EN_IN_TEMP_PROP_DACA 0x20 #define ADT7316_EN_EX_TEMP_PROP_DACB 0x40 -- cgit From 85a1c11913312132d0800ca2c1c42a011f96ea92 Mon Sep 17 00:00:00 2001 From: Jeremy Fertic Date: Tue, 11 Dec 2018 17:54:54 -0700 Subject: staging: iio: adt7316: invert the logic of the check for an ldac pin ADT7316_DA_EN_VIA_DAC_LDCA is set when the dac and ldac registers are being used to update the dacs instead of the ldac pin. ADT7516_SEL_AIN3 is an adc input that shares the ldac pin. Only set these bits if an ldac pin is not being used. This could be backported to stable, but note there are various other bugs that probably make that a waste of time. Signed-off-by: Jeremy Fertic Fixes: 35f6b6b86ede ("staging: iio: new ADT7316/7/8 and ADT7516/7/9 driver") Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 1fa4a4c2b4f3..e5e1f9d6357f 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -2130,7 +2130,7 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus, return ret; } - if (chip->ldac_pin) { + if (!chip->ldac_pin) { chip->config3 |= ADT7316_DA_EN_VIA_DAC_LDCA; if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) chip->config1 |= ADT7516_SEL_AIN3; -- cgit From 5107d16e0aa4f56925c1627830c0e901782350df Mon Sep 17 00:00:00 2001 From: Jeremy Fertic Date: Tue, 11 Dec 2018 17:54:59 -0700 Subject: staging: iio: adt7316: use correct variable in DAC_internal_Vref read The dac internal vref settings are part of the ldac config register rather than the dac config register. Change the variable being used so the read returns the correct result. Whilst a fix, it is for a driver in heavy churn so do not backport to stable without taking considerable care and testing. Signed-off-by: Jeremy Fertic Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index e5e1f9d6357f..c1050dc678cf 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -1061,10 +1061,10 @@ static ssize_t adt7316_show_DAC_internal_Vref(struct device *dev, if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) return sprintf(buf, "0x%x\n", - (chip->dac_config & ADT7516_DAC_IN_VREF_MASK) >> + (chip->ldac_config & ADT7516_DAC_IN_VREF_MASK) >> ADT7516_DAC_IN_VREF_OFFSET); return sprintf(buf, "%d\n", - !!(chip->dac_config & ADT7316_DAC_IN_VREF)); + !!(chip->ldac_config & ADT7316_DAC_IN_VREF)); } static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev, -- cgit From 10bfe7cc1739c22f0aa296b39e53f61e9e3f4d99 Mon Sep 17 00:00:00 2001 From: Jeremy Fertic Date: Tue, 11 Dec 2018 17:55:00 -0700 Subject: staging: iio: adt7316: allow adt751x to use internal vref for all dacs With adt7516/7/9, internal vref is available for dacs a and b, dacs c and d, or all dacs. The driver doesn't currently support internal vref for all dacs. Change the else if to an if so both bits are checked rather than just one or the other. Signed-off-by: Jeremy Fertic Fixes: 35f6b6b86ede ("staging: iio: new ADT7316/7/8 and ADT7516/7/9 driver") Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index c1050dc678cf..ab6de60a94ae 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -1086,7 +1086,7 @@ static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev, ldac_config = chip->ldac_config & (~ADT7516_DAC_IN_VREF_MASK); if (data & 0x1) ldac_config |= ADT7516_DAC_AB_IN_VREF; - else if (data & 0x2) + if (data & 0x2) ldac_config |= ADT7516_DAC_CD_IN_VREF; } else { ret = kstrtou8(buf, 16, &data); -- cgit From 9f287a1c3fffbc10360d7490f5361fff0255a93d Mon Sep 17 00:00:00 2001 From: Jeremy Fertic Date: Tue, 11 Dec 2018 17:55:01 -0700 Subject: staging: iio: adt7316: remove dac vref buffer bypass from adt751x The option to allow the external vref to bypass the reference buffer is only available for adt7316/7/8. Remove the attributes for adt751x as well as the chip->id checks from the show and store functions. Signed-off-by: Jeremy Fertic Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index ab6de60a94ae..0ee925edad04 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -969,9 +969,6 @@ static ssize_t adt7316_show_DA_AB_Vref_bypass(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) - return -EPERM; - return sprintf(buf, "%d\n", !!(chip->dac_config & ADT7316_VREF_BYPASS_DAC_AB)); } @@ -986,9 +983,6 @@ static ssize_t adt7316_store_DA_AB_Vref_bypass(struct device *dev, u8 dac_config; int ret; - if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) - return -EPERM; - dac_config = chip->dac_config & (~ADT7316_VREF_BYPASS_DAC_AB); if (buf[0] == '1') dac_config |= ADT7316_VREF_BYPASS_DAC_AB; @@ -1014,9 +1008,6 @@ static ssize_t adt7316_show_DA_CD_Vref_bypass(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) - return -EPERM; - return sprintf(buf, "%d\n", !!(chip->dac_config & ADT7316_VREF_BYPASS_DAC_CD)); } @@ -1031,9 +1022,6 @@ static ssize_t adt7316_store_DA_CD_Vref_bypass(struct device *dev, u8 dac_config; int ret; - if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) - return -EPERM; - dac_config = chip->dac_config & (~ADT7316_VREF_BYPASS_DAC_CD); if (buf[0] == '1') dac_config |= ADT7316_VREF_BYPASS_DAC_CD; @@ -1710,8 +1698,6 @@ static struct attribute *adt7516_attributes[] = { &iio_dev_attr_DAC_update_mode.dev_attr.attr, &iio_dev_attr_all_DAC_update_modes.dev_attr.attr, &iio_dev_attr_update_DAC.dev_attr.attr, - &iio_dev_attr_DA_AB_Vref_bypass.dev_attr.attr, - &iio_dev_attr_DA_CD_Vref_bypass.dev_attr.attr, &iio_dev_attr_DAC_internal_Vref.dev_attr.attr, &iio_dev_attr_VDD.dev_attr.attr, &iio_dev_attr_in_temp.dev_attr.attr, -- cgit From 32f228cb2ac7ce46cbc3dc0188ea94157039c69a Mon Sep 17 00:00:00 2001 From: Jeremy Fertic Date: Tue, 11 Dec 2018 17:55:02 -0700 Subject: staging: iio: adt7316: change interpretation of write to dac update mode Based on the output of adt7316_show_all_DAC_update_modes() and adt7316_show_DAC_update_mode(), adt7316_store_DAC_update_mode() should expect the user to enter an integer input from 0 to 3. The user input is currently expected to account for the actual bit positions in the register. For example, choosing option 3 would require a write of 0x30 (actually 48 since it expects base 10). To address this inconsistency, create a shift macro to be used in the valid input check as well as the calculation for the register write. Signed-off-by: Jeremy Fertic Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 0ee925edad04..773ce92482db 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -127,6 +127,7 @@ */ #define ADT7316_DA_2VREF_CH_MASK 0xF #define ADT7316_DA_EN_MODE_MASK 0x30 +#define ADT7316_DA_EN_MODE_SHIFT 4 #define ADT7316_DA_EN_MODE_SINGLE 0x00 #define ADT7316_DA_EN_MODE_AB_CD 0x10 #define ADT7316_DA_EN_MODE_ABCD 0x20 @@ -884,11 +885,11 @@ static ssize_t adt7316_store_DAC_update_mode(struct device *dev, return -EPERM; ret = kstrtou8(buf, 10, &data); - if (ret || data > ADT7316_DA_EN_MODE_MASK) + if (ret || data > (ADT7316_DA_EN_MODE_MASK >> ADT7316_DA_EN_MODE_SHIFT)) return -EINVAL; dac_config = chip->dac_config & (~ADT7316_DA_EN_MODE_MASK); - dac_config |= data; + dac_config |= data << ADT7316_DA_EN_MODE_SHIFT; ret = chip->bus.write(chip->bus.client, ADT7316_DAC_CONFIG, dac_config); if (ret) -- cgit From 618ab57f95bd15bfa153a6901a19a8c10e816156 Mon Sep 17 00:00:00 2001 From: Jeremy Fertic Date: Tue, 11 Dec 2018 17:55:03 -0700 Subject: staging: iio: adt7316: correct spelling of ADT7316_DA_EN_VIA_DAC_LDCA Change LDCA to LDAC. Signed-off-by: Jeremy Fertic Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 773ce92482db..23e20dbc873e 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -117,7 +117,7 @@ */ #define ADT7316_ADCLK_22_5 0x1 #define ADT7316_DA_HIGH_RESOLUTION 0x2 -#define ADT7316_DA_EN_VIA_DAC_LDCA 0x8 +#define ADT7316_DA_EN_VIA_DAC_LDAC 0x8 #define ADT7516_AIN_IN_VREF 0x10 #define ADT7316_EN_IN_TEMP_PROP_DACA 0x20 #define ADT7316_EN_EX_TEMP_PROP_DACB 0x40 @@ -852,7 +852,7 @@ static ssize_t adt7316_show_DAC_update_mode(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA)) + if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDAC)) return sprintf(buf, "manual\n"); switch (chip->dac_config & ADT7316_DA_EN_MODE_MASK) { @@ -881,7 +881,7 @@ static ssize_t adt7316_store_DAC_update_mode(struct device *dev, u8 data; int ret; - if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA)) + if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDAC)) return -EPERM; ret = kstrtou8(buf, 10, &data); @@ -912,7 +912,7 @@ static ssize_t adt7316_show_all_DAC_update_modes(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA) + if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDAC) return sprintf(buf, "0 - auto at any MSB DAC writing\n" "1 - auto at MSB DAC AB and CD writing\n" "2 - auto at MSB DAC ABCD writing\n" @@ -934,7 +934,7 @@ static ssize_t adt7316_store_update_DAC(struct device *dev, u8 data; int ret; - if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA) { + if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDAC) { if ((chip->dac_config & ADT7316_DA_EN_MODE_MASK) != ADT7316_DA_EN_MODE_LDAC) return -EPERM; @@ -2118,7 +2118,7 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus, } if (!chip->ldac_pin) { - chip->config3 |= ADT7316_DA_EN_VIA_DAC_LDCA; + chip->config3 |= ADT7316_DA_EN_VIA_DAC_LDAC; if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) chip->config1 |= ADT7516_SEL_AIN3; } -- cgit From 1533e45748783ca971639b1b661509314a13ff8c Mon Sep 17 00:00:00 2001 From: Hardik Singh Rathore Date: Wed, 12 Dec 2018 22:17:46 +0530 Subject: staging: iio: adt7316: drop unnecessary initialization of variables Initialization is unnecessary when the variable is written before it is read. There were some occasions in which the driver would initialize `ret' during declaration without need. Purely a cosmetic change with no functional impact. Signed-off-by: Hardik Singh Rathore Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316-i2c.c | 6 +++--- drivers/staging/iio/addac/adt7316-spi.c | 4 ++-- drivers/staging/iio/addac/adt7316.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c index 2d51bd425662..0f26bc38edc6 100644 --- a/drivers/staging/iio/addac/adt7316-i2c.c +++ b/drivers/staging/iio/addac/adt7316-i2c.c @@ -43,7 +43,7 @@ static int adt7316_i2c_read(void *client, u8 reg, u8 *data) static int adt7316_i2c_write(void *client, u8 reg, u8 data) { struct i2c_client *cl = client; - int ret = 0; + int ret; ret = i2c_smbus_write_byte_data(cl, reg, data); if (ret < 0) @@ -55,7 +55,7 @@ static int adt7316_i2c_write(void *client, u8 reg, u8 data) static int adt7316_i2c_multi_read(void *client, u8 reg, u8 count, u8 *data) { struct i2c_client *cl = client; - int i, ret = 0; + int i, ret; if (count > ADT7316_REG_MAX_ADDR) count = ADT7316_REG_MAX_ADDR; @@ -74,7 +74,7 @@ static int adt7316_i2c_multi_read(void *client, u8 reg, u8 count, u8 *data) static int adt7316_i2c_multi_write(void *client, u8 reg, u8 count, u8 *data) { struct i2c_client *cl = client; - int i, ret = 0; + int i, ret; if (count > ADT7316_REG_MAX_ADDR) count = ADT7316_REG_MAX_ADDR; diff --git a/drivers/staging/iio/addac/adt7316-spi.c b/drivers/staging/iio/addac/adt7316-spi.c index e75827e326a6..8294b9c1e3c2 100644 --- a/drivers/staging/iio/addac/adt7316-spi.c +++ b/drivers/staging/iio/addac/adt7316-spi.c @@ -27,7 +27,7 @@ static int adt7316_spi_multi_read(void *client, u8 reg, u8 count, u8 *data) { struct spi_device *spi_dev = client; u8 cmd[2]; - int ret = 0; + int ret; if (count > ADT7316_REG_MAX_ADDR) count = ADT7316_REG_MAX_ADDR; @@ -56,7 +56,7 @@ static int adt7316_spi_multi_write(void *client, u8 reg, u8 count, u8 *data) { struct spi_device *spi_dev = client; u8 buf[ADT7316_REG_MAX_ADDR + 2]; - int i, ret = 0; + int i, ret; if (count > ADT7316_REG_MAX_ADDR) count = ADT7316_REG_MAX_ADDR; diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 23e20dbc873e..c3a472f76ad0 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -2092,7 +2092,7 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus, struct iio_dev *indio_dev; unsigned short *adt7316_platform_data = dev->platform_data; int irq_type = IRQF_TRIGGER_LOW; - int ret = 0; + int ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*chip)); if (!indio_dev) -- cgit From 7f6b6d553df71431e61dfd2691a184fc7538dbfc Mon Sep 17 00:00:00 2001 From: Shreeya Patel Date: Fri, 14 Dec 2018 01:13:35 +0530 Subject: Staging: iio: adt7316: Add all irq related code in adt7316_irq_setup() ADT7316 driver no more uses platform data and hence use device tree data instead of platform data for assigning irq_type field and implement this in adt7316_irq_setup function. Switch case figures out the type of irq and if it's the default case then assign the default value to the irq_type i.e. irq_type = IRQF_TRIGGER_LOW Move devm_request_threaded_irq() and assignment of chip->config1 into the adt7316_setup_irq() to unclutter the code in probe function. Signed-off-by: Shreeya Patel Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316.c | 52 +++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index c3a472f76ad0..9db49aa186bb 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -1796,6 +1796,43 @@ static irqreturn_t adt7316_event_handler(int irq, void *private) return IRQ_HANDLED; } +static int adt7316_setup_irq(struct iio_dev *indio_dev) +{ + struct adt7316_chip_info *chip = iio_priv(indio_dev); + int irq_type, ret; + + irq_type = irqd_get_trigger_type(irq_get_irq_data(chip->bus.irq)); + + switch (irq_type) { + case IRQF_TRIGGER_HIGH: + case IRQF_TRIGGER_RISING: + break; + case IRQF_TRIGGER_LOW: + case IRQF_TRIGGER_FALLING: + break; + default: + dev_info(&indio_dev->dev, "mode %d unsupported, using IRQF_TRIGGER_LOW\n", + irq_type); + irq_type = IRQF_TRIGGER_LOW; + break; + } + + ret = devm_request_threaded_irq(&indio_dev->dev, chip->bus.irq, + NULL, adt7316_event_handler, + irq_type | IRQF_ONESHOT, + indio_dev->name, indio_dev); + if (ret) { + dev_err(&indio_dev->dev, "failed to request irq %d\n", + chip->bus.irq); + return ret; + } + + if (irq_type & IRQF_TRIGGER_HIGH) + chip->config1 |= ADT7316_INT_POLARITY; + + return 0; +} + /* * Show mask of enabled interrupts in Hex. */ @@ -2090,8 +2127,6 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus, { struct adt7316_chip_info *chip; struct iio_dev *indio_dev; - unsigned short *adt7316_platform_data = dev->platform_data; - int irq_type = IRQF_TRIGGER_LOW; int ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*chip)); @@ -2135,20 +2170,9 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus, indio_dev->modes = INDIO_DIRECT_MODE; if (chip->bus.irq > 0) { - if (adt7316_platform_data[0]) - irq_type = adt7316_platform_data[0]; - - ret = devm_request_threaded_irq(dev, chip->bus.irq, - NULL, - adt7316_event_handler, - irq_type | IRQF_ONESHOT, - indio_dev->name, - indio_dev); + ret = adt7316_setup_irq(indio_dev); if (ret) return ret; - - if (irq_type & IRQF_TRIGGER_HIGH) - chip->config1 |= ADT7316_INT_POLARITY; } ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, chip->config1); -- cgit From c9d07120ab9a704927191ae44729f4b8abba797f Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Sat, 8 Dec 2018 16:19:08 -0200 Subject: staging: iio: ad5933: change regulator binging for vref Set a single voltage regulator for all voltage references. Remove voltage reference value from default platafrom data struct. Signed-off-by: Marcelo Schmitt Signed-off-by: Gabriel Capella Co-developed-by: Gabriel Capella Signed-off-by: Jonathan Cameron --- drivers/staging/iio/impedance-analyzer/ad5933.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 9e52384f5370..730bc397a26b 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -91,7 +91,6 @@ struct ad5933_platform_data { unsigned long ext_clk_hz; - unsigned short vref_mv; }; struct ad5933_state { @@ -113,7 +112,6 @@ struct ad5933_state { }; static struct ad5933_platform_data ad5933_default_pdata = { - .vref_mv = 3300, }; #define AD5933_CHANNEL(_type, _extend_name, _info_mask_separate, _address, \ @@ -691,7 +689,7 @@ static void ad5933_work(struct work_struct *work) static int ad5933_probe(struct i2c_client *client, const struct i2c_device_id *id) { - int ret, voltage_uv = 0; + int ret; struct ad5933_platform_data *pdata = dev_get_platdata(&client->dev); struct ad5933_state *st; struct iio_dev *indio_dev; @@ -718,12 +716,12 @@ static int ad5933_probe(struct i2c_client *client, dev_err(&client->dev, "Failed to enable specified VDD supply\n"); return ret; } - voltage_uv = regulator_get_voltage(st->reg); + ret = regulator_get_voltage(st->reg); + + if (ret < 0) + goto error_disable_reg; - if (voltage_uv) - st->vref_mv = voltage_uv / 1000; - else - st->vref_mv = pdata->vref_mv; + st->vref_mv = ret / 1000; if (pdata->ext_clk_hz) { st->mclk_hz = pdata->ext_clk_hz; -- cgit From 0e0a22aebd64319d0fbe765974ba1e6332d98543 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Sat, 8 Dec 2018 16:19:38 -0200 Subject: staging: iio: ad5933: use clock framework for clock reference Add the option to specify the external clock (MCLK) using the clock framework. Also remove the old platform data structure. Signed-off-by: Marcelo Schmitt Signed-off-by: Gabriel Capella Co-developed-by: Gabriel Capella Signed-off-by: Jonathan Cameron --- drivers/staging/iio/impedance-analyzer/ad5933.c | 43 +++++++++++++------------ 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 730bc397a26b..3134295f014f 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -82,20 +83,10 @@ #define AD5933_POLL_TIME_ms 10 #define AD5933_INIT_EXCITATION_TIME_ms 100 -/** - * struct ad5933_platform_data - platform specific data - * @ext_clk_hz: the external clock frequency in Hz, if not set - * the driver uses the internal clock (16.776 MHz) - * @vref_mv: the external reference voltage in millivolt - */ - -struct ad5933_platform_data { - unsigned long ext_clk_hz; -}; - struct ad5933_state { struct i2c_client *client; struct regulator *reg; + struct clk *mclk; struct delayed_work work; struct mutex lock; /* Protect sensor state */ unsigned long mclk_hz; @@ -111,9 +102,6 @@ struct ad5933_state { unsigned int poll_time_jiffies; }; -static struct ad5933_platform_data ad5933_default_pdata = { -}; - #define AD5933_CHANNEL(_type, _extend_name, _info_mask_separate, _address, \ _scan_index, _realbits) { \ .type = (_type), \ @@ -690,9 +678,9 @@ static int ad5933_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret; - struct ad5933_platform_data *pdata = dev_get_platdata(&client->dev); struct ad5933_state *st; struct iio_dev *indio_dev; + unsigned long ext_clk_hz = 0; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); if (!indio_dev) @@ -704,9 +692,6 @@ static int ad5933_probe(struct i2c_client *client, mutex_init(&st->lock); - if (!pdata) - pdata = &ad5933_default_pdata; - st->reg = devm_regulator_get(&client->dev, "vdd"); if (IS_ERR(st->reg)) return PTR_ERR(st->reg); @@ -723,8 +708,21 @@ static int ad5933_probe(struct i2c_client *client, st->vref_mv = ret / 1000; - if (pdata->ext_clk_hz) { - st->mclk_hz = pdata->ext_clk_hz; + st->mclk = devm_clk_get(&client->dev, "mclk"); + if (IS_ERR(st->mclk) && PTR_ERR(st->mclk) != -ENOENT) { + ret = PTR_ERR(st->mclk); + goto error_disable_reg; + } + + if (!IS_ERR(st->mclk)) { + ret = clk_prepare_enable(st->mclk); + if (ret < 0) + goto error_disable_reg; + ext_clk_hz = clk_get_rate(st->mclk); + } + + if (ext_clk_hz) { + st->mclk_hz = ext_clk_hz; st->ctrl_lb = AD5933_CTRL_EXT_SYSCLK; } else { st->mclk_hz = AD5933_INT_OSC_FREQ_Hz; @@ -744,7 +742,7 @@ static int ad5933_probe(struct i2c_client *client, ret = ad5933_register_ring_funcs_and_init(indio_dev); if (ret) - goto error_disable_reg; + goto error_disable_mclk; ret = ad5933_setup(st); if (ret) @@ -758,6 +756,8 @@ static int ad5933_probe(struct i2c_client *client, error_unreg_ring: iio_kfifo_free(indio_dev->buffer); +error_disable_mclk: + clk_disable_unprepare(st->mclk); error_disable_reg: regulator_disable(st->reg); @@ -772,6 +772,7 @@ static int ad5933_remove(struct i2c_client *client) iio_device_unregister(indio_dev); iio_kfifo_free(indio_dev->buffer); regulator_disable(st->reg); + clk_disable_unprepare(st->mclk); return 0; } -- cgit From 05cf4fe738242183f1237f1b3a28b4479348c0a1 Mon Sep 17 00:00:00 2001 From: Marcelo Schmitt Date: Sat, 8 Dec 2018 16:19:59 -0200 Subject: staging: iio: ad5933: add binding doc for ad5933 Add a devicetree documentation for the ad5933 and ad5934 impedance converter, network analyzer. Signed-off-by: Marcelo Schmitt Signed-off-by: Gabriel Capella Co-Developed-by: Gabriel Capella Signed-off-by: Jonathan Cameron --- .../bindings/iio/impedance-analyzer/ad5933.txt | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/impedance-analyzer/ad5933.txt diff --git a/Documentation/devicetree/bindings/iio/impedance-analyzer/ad5933.txt b/Documentation/devicetree/bindings/iio/impedance-analyzer/ad5933.txt new file mode 100644 index 000000000000..5ff38728ff91 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/impedance-analyzer/ad5933.txt @@ -0,0 +1,26 @@ +Analog Devices AD5933/AD5934 Impedance Converter, Network Analyzer + +https://www.analog.com/media/en/technical-documentation/data-sheets/AD5933.pdf +https://www.analog.com/media/en/technical-documentation/data-sheets/AD5934.pdf + +Required properties: + - compatible : should be one of + "adi,ad5933" + "adi,ad5934" + - reg : the I2C address. + - vdd-supply : The regulator supply for DVDD, AVDD1 and AVDD2 when they + are connected together. + +Optional properties: +- clocks : external clock reference. +- clock-names : must be "mclk" if clocks is set. + +Example for a I2C device node: + + impedance-analyzer@0d { + compatible = "adi,adxl345"; + reg = <0x0d>; + vdd-supply = <&vdd_supply>; + clocks = <&ref_clk>; + clock-names = "mclk"; + }; -- cgit From 243c5c9d7b6250ce5e03cd88e48a40f961251b4e Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Wed, 12 Dec 2018 18:02:27 +0100 Subject: staging: iio: adc: ad7280a: split ad7280_channel_init() to more functions The ad7280_channel_init function has been split into more specific functions to increase the code readability. The setting of channel's scan_type.shift to 0, has been removed, since it is the default value. Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7280a.c | 133 ++++++++++++++++++++++++-------------- 1 file changed, 86 insertions(+), 47 deletions(-) diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index 14f6a3ced060..8439a4e23228 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -97,6 +97,10 @@ #define AD7280A_NUM_CH (AD7280A_AUX_ADC_6 - \ AD7280A_CELL_VOLTAGE_1 + 1) +#define AD7280A_CALC_VOLTAGE_CHAN_NUM(d, c) ((d * AD7280A_CELLS_PER_DEV) + c) +#define AD7280A_CALC_TEMP_CHAN_NUM(d, c) ((d * AD7280A_CELLS_PER_DEV) + \ + c - AD7280A_CELLS_PER_DEV) + #define AD7280A_DEVADDR_MASTER 0 #define AD7280A_DEVADDR_ALL 0x1F /* 5-bit device address is sent LSB first */ @@ -496,63 +500,98 @@ static const struct attribute_group ad7280_attrs_group = { .attrs = ad7280_attributes, }; +static void ad7280_voltage_channel_init(struct iio_chan_spec *chan, int i) +{ + chan->type = IIO_VOLTAGE; + chan->differential = 1; + chan->channel = i; + chan->channel2 = chan->channel + 1; +} + +static void ad7280_temp_channel_init(struct iio_chan_spec *chan, int i) +{ + chan->type = IIO_TEMP; + chan->channel = i; +} + +static void ad7280_common_fields_init(struct iio_chan_spec *chan, int addr, + int cnt) +{ + chan->indexed = 1; + chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); + chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); + chan->address = addr; + chan->scan_index = cnt; + chan->scan_type.sign = 'u'; + chan->scan_type.realbits = 12; + chan->scan_type.storagebits = 32; +} + +static void ad7280_total_voltage_channel_init(struct iio_chan_spec *chan, + int cnt, int dev) +{ + chan->type = IIO_VOLTAGE; + chan->differential = 1; + chan->channel = 0; + chan->channel2 = dev * AD7280A_CELLS_PER_DEV; + chan->address = AD7280A_ALL_CELLS; + chan->indexed = 1; + chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); + chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); + chan->scan_index = cnt; + chan->scan_type.sign = 'u'; + chan->scan_type.realbits = 32; + chan->scan_type.storagebits = 32; +} + +static void ad7280_timestamp_channel_init(struct iio_chan_spec *chan, int cnt) +{ + chan->type = IIO_TIMESTAMP; + chan->channel = -1; + chan->scan_index = cnt; + chan->scan_type.sign = 's'; + chan->scan_type.realbits = 64; + chan->scan_type.storagebits = 64; +} + +static void ad7280_init_dev_channels(struct ad7280_state *st, int dev, int *cnt) +{ + int addr, ch, i; + struct iio_chan_spec *chan; + + for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_AUX_ADC_6; ch++) { + chan = &st->channels[*cnt]; + + if (ch < AD7280A_AUX_ADC_1) { + i = AD7280A_CALC_VOLTAGE_CHAN_NUM(dev, ch); + ad7280_voltage_channel_init(chan, i); + } else { + i = AD7280A_CALC_TEMP_CHAN_NUM(dev, ch); + ad7280_temp_channel_init(chan, i); + } + + addr = ad7280a_devaddr(dev) << 8 | ch; + ad7280_common_fields_init(chan, addr, *cnt); + + (*cnt)++; + } +} + static int ad7280_channel_init(struct ad7280_state *st) { - int dev, ch, cnt; + int dev, cnt = 0; st->channels = devm_kcalloc(&st->spi->dev, (st->slave_num + 1) * 12 + 2, sizeof(*st->channels), GFP_KERNEL); if (!st->channels) return -ENOMEM; - for (dev = 0, cnt = 0; dev <= st->slave_num; dev++) - for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_AUX_ADC_6; - ch++, cnt++) { - if (ch < AD7280A_AUX_ADC_1) { - st->channels[cnt].type = IIO_VOLTAGE; - st->channels[cnt].differential = 1; - st->channels[cnt].channel = (dev * 6) + ch; - st->channels[cnt].channel2 = - st->channels[cnt].channel + 1; - } else { - st->channels[cnt].type = IIO_TEMP; - st->channels[cnt].channel = (dev * 6) + ch - 6; - } - st->channels[cnt].indexed = 1; - st->channels[cnt].info_mask_separate = - BIT(IIO_CHAN_INFO_RAW); - st->channels[cnt].info_mask_shared_by_type = - BIT(IIO_CHAN_INFO_SCALE); - st->channels[cnt].address = - ad7280a_devaddr(dev) << 8 | ch; - st->channels[cnt].scan_index = cnt; - st->channels[cnt].scan_type.sign = 'u'; - st->channels[cnt].scan_type.realbits = 12; - st->channels[cnt].scan_type.storagebits = 32; - st->channels[cnt].scan_type.shift = 0; - } + for (dev = 0; dev <= st->slave_num; dev++) + ad7280_init_dev_channels(st, dev, &cnt); - st->channels[cnt].type = IIO_VOLTAGE; - st->channels[cnt].differential = 1; - st->channels[cnt].channel = 0; - st->channels[cnt].channel2 = dev * 6; - st->channels[cnt].address = AD7280A_ALL_CELLS; - st->channels[cnt].indexed = 1; - st->channels[cnt].info_mask_separate = BIT(IIO_CHAN_INFO_RAW); - st->channels[cnt].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); - st->channels[cnt].scan_index = cnt; - st->channels[cnt].scan_type.sign = 'u'; - st->channels[cnt].scan_type.realbits = 32; - st->channels[cnt].scan_type.storagebits = 32; - st->channels[cnt].scan_type.shift = 0; + ad7280_total_voltage_channel_init(&st->channels[cnt], cnt, dev); cnt++; - st->channels[cnt].type = IIO_TIMESTAMP; - st->channels[cnt].channel = -1; - st->channels[cnt].scan_index = cnt; - st->channels[cnt].scan_type.sign = 's'; - st->channels[cnt].scan_type.realbits = 64; - st->channels[cnt].scan_type.storagebits = 64; - st->channels[cnt].scan_type.shift = 0; + ad7280_timestamp_channel_init(&st->channels[cnt], cnt); return cnt + 1; } -- cgit From 4b6374577fe751f60ffc24c7b95ce803a22b2476 Mon Sep 17 00:00:00 2001 From: Slawomir Stepien Date: Wed, 12 Dec 2018 18:02:28 +0100 Subject: staging: iio: adc: ad7280a: split ad7280_attr_init() to more functions The ad7280_attr_init function has been split into more specific functions to increase the code readability. Signed-off-by: Slawomir Stepien Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7280a.c | 110 +++++++++++++++++++++++++------------- 1 file changed, 72 insertions(+), 38 deletions(-) diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c index 8439a4e23228..d9df12665176 100644 --- a/drivers/staging/iio/adc/ad7280a.c +++ b/drivers/staging/iio/adc/ad7280a.c @@ -596,11 +596,75 @@ static int ad7280_channel_init(struct ad7280_state *st) return cnt + 1; } -static int ad7280_attr_init(struct ad7280_state *st) +static int ad7280_balance_switch_attr_init(struct iio_dev_attr *attr, + struct device *dev, int addr, int i) +{ + attr->address = addr; + attr->dev_attr.attr.mode = 0644; + attr->dev_attr.show = ad7280_show_balance_sw; + attr->dev_attr.store = ad7280_store_balance_sw; + attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, + "in%d-in%d_balance_switch_en", + i, i + 1); + if (!attr->dev_attr.attr.name) + return -ENOMEM; + + return 0; +} + +static int ad7280_balance_timer_attr_init(struct iio_dev_attr *attr, + struct device *dev, int addr, int i) +{ + attr->address = addr; + attr->dev_attr.attr.mode = 0644; + attr->dev_attr.show = ad7280_show_balance_timer; + attr->dev_attr.store = ad7280_store_balance_timer; + attr->dev_attr.attr.name = devm_kasprintf(dev, GFP_KERNEL, + "in%d-in%d_balance_timer", + i, i + 1); + if (!attr->dev_attr.attr.name) + return -ENOMEM; + + return 0; +} + +static int ad7280_init_dev_attrs(struct ad7280_state *st, int dev, int *cnt) { - int dev, ch, cnt; - unsigned int index; + int addr, ch, i, ret; struct iio_dev_attr *iio_attr; + struct device *sdev = &st->spi->dev; + + for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_CELL_VOLTAGE_6; ch++) { + iio_attr = &st->iio_attr[*cnt]; + addr = ad7280a_devaddr(dev) << 8 | ch; + i = dev * AD7280A_CELLS_PER_DEV + ch; + + ret = ad7280_balance_switch_attr_init(iio_attr, sdev, addr, i); + if (ret < 0) + return ret; + + ad7280_attributes[*cnt] = &iio_attr->dev_attr.attr; + + (*cnt)++; + iio_attr = &st->iio_attr[*cnt]; + addr = ad7280a_devaddr(dev) << 8 | (AD7280A_CB1_TIMER + ch); + + ret = ad7280_balance_timer_attr_init(iio_attr, sdev, addr, i); + if (ret < 0) + return ret; + + ad7280_attributes[*cnt] = &iio_attr->dev_attr.attr; + (*cnt)++; + } + + ad7280_attributes[*cnt] = NULL; + + return 0; +} + +static int ad7280_attr_init(struct ad7280_state *st) +{ + int dev, cnt = 0, ret; st->iio_attr = devm_kcalloc(&st->spi->dev, 2, sizeof(*st->iio_attr) * (st->slave_num + 1) * AD7280A_CELLS_PER_DEV, @@ -608,41 +672,11 @@ static int ad7280_attr_init(struct ad7280_state *st) if (!st->iio_attr) return -ENOMEM; - for (dev = 0, cnt = 0; dev <= st->slave_num; dev++) - for (ch = AD7280A_CELL_VOLTAGE_1; ch <= AD7280A_CELL_VOLTAGE_6; - ch++, cnt++) { - iio_attr = &st->iio_attr[cnt]; - index = dev * AD7280A_CELLS_PER_DEV + ch; - iio_attr->address = ad7280a_devaddr(dev) << 8 | ch; - iio_attr->dev_attr.attr.mode = 0644; - iio_attr->dev_attr.show = ad7280_show_balance_sw; - iio_attr->dev_attr.store = ad7280_store_balance_sw; - iio_attr->dev_attr.attr.name = - devm_kasprintf(&st->spi->dev, GFP_KERNEL, - "in%d-in%d_balance_switch_en", - index, index + 1); - if (!iio_attr->dev_attr.attr.name) - return -ENOMEM; - - ad7280_attributes[cnt] = &iio_attr->dev_attr.attr; - cnt++; - iio_attr = &st->iio_attr[cnt]; - iio_attr->address = ad7280a_devaddr(dev) << 8 | - (AD7280A_CB1_TIMER + ch); - iio_attr->dev_attr.attr.mode = 0644; - iio_attr->dev_attr.show = ad7280_show_balance_timer; - iio_attr->dev_attr.store = ad7280_store_balance_timer; - iio_attr->dev_attr.attr.name = - devm_kasprintf(&st->spi->dev, GFP_KERNEL, - "in%d-in%d_balance_timer", - index, index + 1); - if (!iio_attr->dev_attr.attr.name) - return -ENOMEM; - - ad7280_attributes[cnt] = &iio_attr->dev_attr.attr; - } - - ad7280_attributes[cnt] = NULL; + for (dev = 0; dev <= st->slave_num; dev++) { + ret = ad7280_init_dev_attrs(st, dev, &cnt); + if (ret < 0) + return ret; + } return 0; } -- cgit From f1b753a0f866a834f5681506ac29b6ca0ee902b2 Mon Sep 17 00:00:00 2001 From: Hardik Singh Rathore Date: Wed, 12 Dec 2018 23:27:07 +0530 Subject: staging: iio: ad7816: drop unnecessary initialization of variables Initialization is unnecessary when the variable is written before it is read. There were some occasions in which the driver would initialize `ret' during declaration without need. Signed-off-by: Hardik Singh Rathore Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7816.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c index 5209651a1b25..ee50e7296795 100644 --- a/drivers/staging/iio/adc/ad7816.c +++ b/drivers/staging/iio/adc/ad7816.c @@ -65,7 +65,7 @@ enum ad7816_type { static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data) { struct spi_device *spi_dev = chip->spi_dev; - int ret = 0; + int ret; __be16 buf; gpiod_set_value(chip->rdwr_pin, 1); @@ -106,7 +106,7 @@ static int ad7816_spi_read(struct ad7816_chip_info *chip, u16 *data) static int ad7816_spi_write(struct ad7816_chip_info *chip, u8 data) { struct spi_device *spi_dev = chip->spi_dev; - int ret = 0; + int ret; gpiod_set_value(chip->rdwr_pin, 1); gpiod_set_value(chip->rdwr_pin, 0); @@ -354,8 +354,7 @@ static int ad7816_probe(struct spi_device *spi_dev) { struct ad7816_chip_info *chip; struct iio_dev *indio_dev; - int ret = 0; - int i; + int i, ret; indio_dev = devm_iio_device_alloc(&spi_dev->dev, sizeof(*chip)); if (!indio_dev) -- cgit From 17abc9ec68b73ddeb262a507a62421016b9c54d5 Mon Sep 17 00:00:00 2001 From: Tomasz Duszynski Date: Fri, 14 Dec 2018 19:28:01 +0100 Subject: iio: add IIO_MASSCONCENTRATION channel type Measuring particulate matter in ug / m3 (micro-grams per cubic meter) is de facto standard. Existing air quality sensors usually follow this convention and are capable of returning measurements using this unit. IIO currently does not offer suitable channel type for this type of measurements hence this patch adds this. In addition, extra modifiers are introduced used for distinguishing between fine pm1, pm2p5 and coarse pm4, pm10 particle measurements, i.e IIO_MOD_PM1, IIO_MOD_PM25 and IIO_MOD_PM4, IIO_MOD_PM10. pmX consists of particles with aerodynamic diameter less or equal to X micrometers. Signed-off-by: Tomasz Duszynski Acked-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 17 ++++++++++++++++- drivers/iio/industrialio-core.c | 5 +++++ include/uapi/linux/iio/types.h | 5 +++++ tools/iio/iio_event_monitor.c | 10 ++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 8127a08e366d..67fd88bf7910 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1684,4 +1684,19 @@ KernelVersion: 4.18 Contact: linux-iio@vger.kernel.org Description: Raw (unscaled) phase difference reading from channel Y - that can be processed to radians. \ No newline at end of file + that can be processed to radians. + +What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm1_input +What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm1_input +What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm2p5_input +What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm2p5_input +What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm4_input +What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm4_input +What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm10_input +What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm10_input +KernelVersion: 4.22 +Contact: linux-iio@vger.kernel.org +Description: + Mass concentration reading of particulate matter in ug / m3. + pmX consists of particles with aerodynamic diameter less or + equal to X micrometers. diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 4f5cd9f60870..4700fd5d8c90 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -87,6 +87,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_GRAVITY] = "gravity", [IIO_POSITIONRELATIVE] = "positionrelative", [IIO_PHASE] = "phase", + [IIO_MASSCONCENTRATION] = "massconcentration", }; static const char * const iio_modifier_names[] = { @@ -127,6 +128,10 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_Q] = "q", [IIO_MOD_CO2] = "co2", [IIO_MOD_VOC] = "voc", + [IIO_MOD_PM1] = "pm1", + [IIO_MOD_PM2P5] = "pm2p5", + [IIO_MOD_PM4] = "pm4", + [IIO_MOD_PM10] = "pm10", }; /* relies on pairs of these shared then separate */ diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index 92baabc103ac..c59adac24b1c 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -46,6 +46,7 @@ enum iio_chan_type { IIO_GRAVITY, IIO_POSITIONRELATIVE, IIO_PHASE, + IIO_MASSCONCENTRATION, }; enum iio_modifier { @@ -87,6 +88,10 @@ enum iio_modifier { IIO_MOD_VOC, IIO_MOD_LIGHT_UV, IIO_MOD_LIGHT_DUV, + IIO_MOD_PM1, + IIO_MOD_PM2P5, + IIO_MOD_PM4, + IIO_MOD_PM10, }; enum iio_event_type { diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c index ac2de6b7e89f..f6b8003fbe3c 100644 --- a/tools/iio/iio_event_monitor.c +++ b/tools/iio/iio_event_monitor.c @@ -60,6 +60,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_GRAVITY] = "gravity", [IIO_POSITIONRELATIVE] = "positionrelative", [IIO_PHASE] = "phase", + [IIO_MASSCONCENTRATION] = "massconcentration", }; static const char * const iio_ev_type_text[] = { @@ -115,6 +116,10 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_Q] = "q", [IIO_MOD_CO2] = "co2", [IIO_MOD_VOC] = "voc", + [IIO_MOD_PM1] = "pm1", + [IIO_MOD_PM2P5] = "pm2p5", + [IIO_MOD_PM4] = "pm4", + [IIO_MOD_PM10] = "pm10", }; static bool event_is_known(struct iio_event_data *event) @@ -156,6 +161,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_GRAVITY: case IIO_POSITIONRELATIVE: case IIO_PHASE: + case IIO_MASSCONCENTRATION: break; default: return false; @@ -200,6 +206,10 @@ static bool event_is_known(struct iio_event_data *event) case IIO_MOD_Q: case IIO_MOD_CO2: case IIO_MOD_VOC: + case IIO_MOD_PM1: + case IIO_MOD_PM2P5: + case IIO_MOD_PM4: + case IIO_MOD_PM10: break; default: return false; -- cgit From 232e0f6ddeaee104d64675fe7d0cc142cf955f35 Mon Sep 17 00:00:00 2001 From: Tomasz Duszynski Date: Fri, 14 Dec 2018 19:28:02 +0100 Subject: iio: chemical: add support for Sensirion SPS30 sensor Add support for Sensirion SPS30 particulate matter sensor. Signed-off-by: Tomasz Duszynski Signed-off-by: Jonathan Cameron --- drivers/iio/chemical/Kconfig | 11 ++ drivers/iio/chemical/Makefile | 1 + drivers/iio/chemical/sps30.c | 407 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 419 insertions(+) create mode 100644 drivers/iio/chemical/sps30.c diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index b8e005be4f87..57832b4360e9 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -61,6 +61,17 @@ config IAQCORE iAQ-Core Continuous/Pulsed VOC (Volatile Organic Compounds) sensors +config SPS30 + tristate "SPS30 particulate matter sensor" + depends on I2C + select CRC8 + help + Say Y here to build support for the Sensirion SPS30 particulate + matter sensor. + + To compile this driver as a module, choose M here: the module will + be called sps30. + config VZ89X tristate "SGX Sensortech MiCS VZ89X VOC sensor" depends on I2C diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile index 2f4c4ba4d781..9f42f4252151 100644 --- a/drivers/iio/chemical/Makefile +++ b/drivers/iio/chemical/Makefile @@ -9,4 +9,5 @@ obj-$(CONFIG_BME680_I2C) += bme680_i2c.o obj-$(CONFIG_BME680_SPI) += bme680_spi.o obj-$(CONFIG_CCS811) += ccs811.o obj-$(CONFIG_IAQCORE) += ams-iaq-core.o +obj-$(CONFIG_SPS30) += sps30.o obj-$(CONFIG_VZ89X) += vz89x.o diff --git a/drivers/iio/chemical/sps30.c b/drivers/iio/chemical/sps30.c new file mode 100644 index 000000000000..fa3cd409b90b --- /dev/null +++ b/drivers/iio/chemical/sps30.c @@ -0,0 +1,407 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sensirion SPS30 particulate matter sensor driver + * + * Copyright (c) Tomasz Duszynski + * + * I2C slave address: 0x69 + * + * TODO: + * - support for turning on fan cleaning + * - support for reading/setting auto cleaning interval + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPS30_CRC8_POLYNOMIAL 0x31 +/* max number of bytes needed to store PM measurements or serial string */ +#define SPS30_MAX_READ_SIZE 48 +/* sensor measures reliably up to 3000 ug / m3 */ +#define SPS30_MAX_PM 3000 + +/* SPS30 commands */ +#define SPS30_START_MEAS 0x0010 +#define SPS30_STOP_MEAS 0x0104 +#define SPS30_RESET 0xd304 +#define SPS30_READ_DATA_READY_FLAG 0x0202 +#define SPS30_READ_DATA 0x0300 +#define SPS30_READ_SERIAL 0xd033 + +enum { + PM1, + PM2P5, + PM4, + PM10, +}; + +struct sps30_state { + struct i2c_client *client; + /* + * Guards against concurrent access to sensor registers. + * Must be held whenever sequence of commands is to be executed. + */ + struct mutex lock; +}; + +DECLARE_CRC8_TABLE(sps30_crc8_table); + +static int sps30_write_then_read(struct sps30_state *state, u8 *txbuf, + int txsize, u8 *rxbuf, int rxsize) +{ + int ret; + + /* + * Sensor does not support repeated start so instead of + * sending two i2c messages in a row we just send one by one. + */ + ret = i2c_master_send(state->client, txbuf, txsize); + if (ret != txsize) + return ret < 0 ? ret : -EIO; + + if (!rxbuf) + return 0; + + ret = i2c_master_recv(state->client, rxbuf, rxsize); + if (ret != rxsize) + return ret < 0 ? ret : -EIO; + + return 0; +} + +static int sps30_do_cmd(struct sps30_state *state, u16 cmd, u8 *data, int size) +{ + /* + * Internally sensor stores measurements in a following manner: + * + * PM1: upper two bytes, crc8, lower two bytes, crc8 + * PM2P5: upper two bytes, crc8, lower two bytes, crc8 + * PM4: upper two bytes, crc8, lower two bytes, crc8 + * PM10: upper two bytes, crc8, lower two bytes, crc8 + * + * What follows next are number concentration measurements and + * typical particle size measurement which we omit. + */ + u8 buf[SPS30_MAX_READ_SIZE] = { cmd >> 8, cmd }; + int i, ret = 0; + + switch (cmd) { + case SPS30_START_MEAS: + buf[2] = 0x03; + buf[3] = 0x00; + buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE); + ret = sps30_write_then_read(state, buf, 5, NULL, 0); + break; + case SPS30_STOP_MEAS: + case SPS30_RESET: + ret = sps30_write_then_read(state, buf, 2, NULL, 0); + break; + case SPS30_READ_DATA_READY_FLAG: + case SPS30_READ_DATA: + case SPS30_READ_SERIAL: + /* every two data bytes are checksummed */ + size += size / 2; + ret = sps30_write_then_read(state, buf, 2, buf, size); + break; + } + + if (ret) + return ret; + + /* validate received data and strip off crc bytes */ + for (i = 0; i < size; i += 3) { + u8 crc = crc8(sps30_crc8_table, &buf[i], 2, CRC8_INIT_VALUE); + + if (crc != buf[i + 2]) { + dev_err(&state->client->dev, + "data integrity check failed\n"); + return -EIO; + } + + *data++ = buf[i]; + *data++ = buf[i + 1]; + } + + return 0; +} + +static s32 sps30_float_to_int_clamped(const u8 *fp) +{ + int val = get_unaligned_be32(fp); + int mantissa = val & GENMASK(22, 0); + /* this is fine since passed float is always non-negative */ + int exp = val >> 23; + int fraction, shift; + + /* special case 0 */ + if (!exp && !mantissa) + return 0; + + exp -= 127; + if (exp < 0) { + /* return values ranging from 1 to 99 */ + return ((((1 << 23) + mantissa) * 100) >> 23) >> (-exp); + } + + /* return values ranging from 100 to 300000 */ + shift = 23 - exp; + val = (1 << exp) + (mantissa >> shift); + if (val >= SPS30_MAX_PM) + return SPS30_MAX_PM * 100; + + fraction = mantissa & GENMASK(shift - 1, 0); + + return val * 100 + ((fraction * 100) >> shift); +} + +static int sps30_do_meas(struct sps30_state *state, s32 *data, int size) +{ + int i, ret, tries = 5; + u8 tmp[16]; + + while (tries--) { + ret = sps30_do_cmd(state, SPS30_READ_DATA_READY_FLAG, tmp, 2); + if (ret) + return -EIO; + + /* new measurements ready to be read */ + if (tmp[1] == 1) + break; + + msleep_interruptible(300); + } + + if (!tries) + return -ETIMEDOUT; + + ret = sps30_do_cmd(state, SPS30_READ_DATA, tmp, sizeof(int) * size); + if (ret) + return ret; + + for (i = 0; i < size; i++) + data[i] = sps30_float_to_int_clamped(&tmp[4 * i]); + + return 0; +} + +static irqreturn_t sps30_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct sps30_state *state = iio_priv(indio_dev); + int ret; + s32 data[4 + 2]; /* PM1, PM2P5, PM4, PM10, timestamp */ + + mutex_lock(&state->lock); + ret = sps30_do_meas(state, data, 4); + mutex_unlock(&state->lock); + if (ret) + goto err; + + iio_push_to_buffers_with_timestamp(indio_dev, data, + iio_get_time_ns(indio_dev)); +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int sps30_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct sps30_state *state = iio_priv(indio_dev); + int data[4], ret = -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_MASSCONCENTRATION: + mutex_lock(&state->lock); + /* read up to the number of bytes actually needed */ + switch (chan->channel2) { + case IIO_MOD_PM1: + ret = sps30_do_meas(state, data, 1); + break; + case IIO_MOD_PM2P5: + ret = sps30_do_meas(state, data, 2); + break; + case IIO_MOD_PM4: + ret = sps30_do_meas(state, data, 3); + break; + case IIO_MOD_PM10: + ret = sps30_do_meas(state, data, 4); + break; + } + mutex_unlock(&state->lock); + if (ret) + return ret; + + *val = data[chan->address] / 100; + *val2 = (data[chan->address] % 100) * 10000; + + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_MASSCONCENTRATION: + switch (chan->channel2) { + case IIO_MOD_PM1: + case IIO_MOD_PM2P5: + case IIO_MOD_PM4: + case IIO_MOD_PM10: + *val = 0; + *val2 = 10000; + + return IIO_VAL_INT_PLUS_MICRO; + } + default: + return -EINVAL; + } + } + + return -EINVAL; +} + +static const struct iio_info sps30_info = { + .read_raw = sps30_read_raw, +}; + +#define SPS30_CHAN(_index, _mod) { \ + .type = IIO_MASSCONCENTRATION, \ + .modified = 1, \ + .channel2 = IIO_MOD_ ## _mod, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .address = _mod, \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 19, \ + .storagebits = 32, \ + .endianness = IIO_CPU, \ + }, \ +} + +static const struct iio_chan_spec sps30_channels[] = { + SPS30_CHAN(0, PM1), + SPS30_CHAN(1, PM2P5), + SPS30_CHAN(2, PM4), + SPS30_CHAN(3, PM10), + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +static void sps30_stop_meas(void *data) +{ + struct sps30_state *state = data; + + sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); +} + +static const unsigned long sps30_scan_masks[] = { 0x0f, 0x00 }; + +static int sps30_probe(struct i2c_client *client) +{ + struct iio_dev *indio_dev; + struct sps30_state *state; + u8 buf[32]; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -EOPNOTSUPP; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*state)); + if (!indio_dev) + return -ENOMEM; + + state = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + state->client = client; + indio_dev->dev.parent = &client->dev; + indio_dev->info = &sps30_info; + indio_dev->name = client->name; + indio_dev->channels = sps30_channels; + indio_dev->num_channels = ARRAY_SIZE(sps30_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->available_scan_masks = sps30_scan_masks; + + mutex_init(&state->lock); + crc8_populate_msb(sps30_crc8_table, SPS30_CRC8_POLYNOMIAL); + + ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0); + if (ret) { + dev_err(&client->dev, "failed to reset device\n"); + return ret; + } + msleep(300); + /* + * Power-on-reset causes sensor to produce some glitch on i2c bus and + * some controllers end up in error state. Recover simply by placing + * some data on the bus, for example STOP_MEAS command, which + * is NOP in this case. + */ + sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); + + ret = sps30_do_cmd(state, SPS30_READ_SERIAL, buf, sizeof(buf)); + if (ret) { + dev_err(&client->dev, "failed to read serial number\n"); + return ret; + } + /* returned serial number is already NUL terminated */ + dev_info(&client->dev, "serial number: %s\n", buf); + + ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0); + if (ret) { + dev_err(&client->dev, "failed to start measurement\n"); + return ret; + } + + ret = devm_add_action_or_reset(&client->dev, sps30_stop_meas, state); + if (ret) + return ret; + + ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL, + sps30_trigger_handler, NULL); + if (ret) + return ret; + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct i2c_device_id sps30_id[] = { + { "sps30" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, sps30_id); + +static const struct of_device_id sps30_of_match[] = { + { .compatible = "sensirion,sps30" }, + { } +}; +MODULE_DEVICE_TABLE(of, sps30_of_match); + +static struct i2c_driver sps30_driver = { + .driver = { + .name = "sps30", + .of_match_table = sps30_of_match, + }, + .id_table = sps30_id, + .probe_new = sps30_probe, +}; +module_i2c_driver(sps30_driver); + +MODULE_AUTHOR("Tomasz Duszynski "); +MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor driver"); +MODULE_LICENSE("GPL v2"); -- cgit From bf81deacc6facb6fada5b3bb31a832ef77cf7e87 Mon Sep 17 00:00:00 2001 From: Tomasz Duszynski Date: Fri, 14 Dec 2018 19:28:03 +0100 Subject: dt-bindings: iio: chemical: sps30: add device tree support Add device tree support for Sensirion SPS30 particulate matter sensor. Signed-off-by: Tomasz Duszynski Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/chemical/sensirion,sps30.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/chemical/sensirion,sps30.txt diff --git a/Documentation/devicetree/bindings/iio/chemical/sensirion,sps30.txt b/Documentation/devicetree/bindings/iio/chemical/sensirion,sps30.txt new file mode 100644 index 000000000000..6eee2709b5b6 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/chemical/sensirion,sps30.txt @@ -0,0 +1,12 @@ +* Sensirion SPS30 particulate matter sensor + +Required properties: +- compatible: must be "sensirion,sps30" +- reg: the I2C address of the sensor + +Example: + +sps30@69 { + compatible = "sensirion,sps30"; + reg = <0x69>; +}; -- cgit From b170f7d48443d1ea3e4ffbf409025b5e5b1146fe Mon Sep 17 00:00:00 2001 From: Andreas Brauchli Date: Thu, 13 Dec 2018 15:43:22 +0100 Subject: iio: Add modifiers for ethanol and H2 gases Add ethanol and H2 gas modifiers: * IIO_MOD_ETHANOL * IIO_MOD_H2 Signed-off-by: Andreas Brauchli Acked-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 4 ++++ include/uapi/linux/iio/types.h | 2 ++ tools/iio/iio_event_monitor.c | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 67fd88bf7910..864f8efd12e5 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1554,6 +1554,10 @@ What: /sys/bus/iio/devices/iio:deviceX/in_concentration_raw What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_raw What: /sys/bus/iio/devices/iio:deviceX/in_concentration_co2_raw What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_co2_raw +What: /sys/bus/iio/devices/iio:deviceX/in_concentration_ethanol_raw +What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_ethanol_raw +What: /sys/bus/iio/devices/iio:deviceX/in_concentration_h2_raw +What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_h2_raw What: /sys/bus/iio/devices/iio:deviceX/in_concentration_voc_raw What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_voc_raw KernelVersion: 4.3 diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index c59adac24b1c..fdd81affca4b 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -92,6 +92,8 @@ enum iio_modifier { IIO_MOD_PM2P5, IIO_MOD_PM4, IIO_MOD_PM10, + IIO_MOD_ETHANOL, + IIO_MOD_H2, }; enum iio_event_type { diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c index f6b8003fbe3c..7bf9bde28bcc 100644 --- a/tools/iio/iio_event_monitor.c +++ b/tools/iio/iio_event_monitor.c @@ -115,6 +115,8 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_I] = "i", [IIO_MOD_Q] = "q", [IIO_MOD_CO2] = "co2", + [IIO_MOD_ETHANOL] = "ethanol", + [IIO_MOD_H2] = "h2", [IIO_MOD_VOC] = "voc", [IIO_MOD_PM1] = "pm1", [IIO_MOD_PM2P5] = "pm2p5", @@ -205,6 +207,8 @@ static bool event_is_known(struct iio_event_data *event) case IIO_MOD_I: case IIO_MOD_Q: case IIO_MOD_CO2: + case IIO_MOD_ETHANOL: + case IIO_MOD_H2: case IIO_MOD_VOC: case IIO_MOD_PM1: case IIO_MOD_PM2P5: -- cgit From ce514124161ac2ceb13d10b6c40cbf05c8f0cc91 Mon Sep 17 00:00:00 2001 From: Andreas Brauchli Date: Thu, 13 Dec 2018 15:43:23 +0100 Subject: iio: chemical: sgp30: Support Sensirion SGP30/SGPC3 sensors Support Sensirion SGP30 and SGPC3 multi-pixel I2C gas sensors Supported Features: * Indoor Air Quality (IAQ) concentrations for - tVOC (in_concentration_voc_input) - CO2eq (in_concentration_co2_input) - SGP30 only IAQ concentrations are periodically read out by a background thread to allow the sensor to maintain its internal baseline. * Gas concentration signals - Ethanol (in_concentration_ethanol_raw) - H2 (in_concentration_h2_raw) - SGP30 only https://www.sensirion.com/file/datasheet_sgp30 https://www.sensirion.com/file/datasheet_sgpc3 Signed-off-by: Andreas Brauchli Signed-off-by: Jonathan Cameron --- drivers/iio/chemical/Makefile | 1 + drivers/iio/chemical/sgp30.c | 591 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 592 insertions(+) create mode 100644 drivers/iio/chemical/sgp30.c diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile index 9f42f4252151..65bf0f89c0e4 100644 --- a/drivers/iio/chemical/Makefile +++ b/drivers/iio/chemical/Makefile @@ -9,5 +9,6 @@ obj-$(CONFIG_BME680_I2C) += bme680_i2c.o obj-$(CONFIG_BME680_SPI) += bme680_spi.o obj-$(CONFIG_CCS811) += ccs811.o obj-$(CONFIG_IAQCORE) += ams-iaq-core.o +obj-$(CONFIG_SENSIRION_SGP30) += sgp30.o obj-$(CONFIG_SPS30) += sps30.o obj-$(CONFIG_VZ89X) += vz89x.o diff --git a/drivers/iio/chemical/sgp30.c b/drivers/iio/chemical/sgp30.c new file mode 100644 index 000000000000..8cc8fe5e356d --- /dev/null +++ b/drivers/iio/chemical/sgp30.c @@ -0,0 +1,591 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * sgp30.c - Support for Sensirion SGP Gas Sensors + * + * Copyright (C) 2018 Andreas Brauchli + * + * I2C slave address: 0x58 + * + * Datasheets: + * https://www.sensirion.com/file/datasheet_sgp30 + * https://www.sensirion.com/file/datasheet_sgpc3 + * + * TODO: + * - baseline support + * - humidity compensation + * - power mode switching (SGPC3) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SGP_WORD_LEN 2 +#define SGP_CRC8_POLYNOMIAL 0x31 +#define SGP_CRC8_INIT 0xff +#define SGP_CRC8_LEN 1 +#define SGP_CMD(cmd_word) cpu_to_be16(cmd_word) +#define SGP_CMD_DURATION_US 12000 +#define SGP_MEASUREMENT_DURATION_US 50000 +#define SGP_CMD_LEN SGP_WORD_LEN +#define SGP_CMD_MAX_BUF_SIZE (SGP_CMD_LEN + 2 * SGP_WORD_LEN) +#define SGP_MEASUREMENT_LEN 2 +#define SGP30_MEASURE_INTERVAL_HZ 1 +#define SGPC3_MEASURE_INTERVAL_HZ 2 +#define SGP_VERS_PRODUCT(data) ((((data)->feature_set) & 0xf000) >> 12) +#define SGP_VERS_RESERVED(data) ((((data)->feature_set) & 0x0800) >> 11) +#define SGP_VERS_GEN(data) ((((data)->feature_set) & 0x0600) >> 9) +#define SGP_VERS_ENG_BIT(data) ((((data)->feature_set) & 0x0100) >> 8) +#define SGP_VERS_MAJOR(data) ((((data)->feature_set) & 0x00e0) >> 5) +#define SGP_VERS_MINOR(data) (((data)->feature_set) & 0x001f) + +DECLARE_CRC8_TABLE(sgp_crc8_table); + +enum sgp_product_id { + SGP30 = 0, + SGPC3, +}; + +enum sgp30_channel_idx { + SGP30_IAQ_TVOC_IDX = 0, + SGP30_IAQ_CO2EQ_IDX, + SGP30_SIG_ETOH_IDX, + SGP30_SIG_H2_IDX, +}; + +enum sgpc3_channel_idx { + SGPC3_IAQ_TVOC_IDX = 10, + SGPC3_SIG_ETOH_IDX, +}; + +enum sgp_cmd { + SGP_CMD_IAQ_INIT = SGP_CMD(0x2003), + SGP_CMD_IAQ_MEASURE = SGP_CMD(0x2008), + SGP_CMD_GET_FEATURE_SET = SGP_CMD(0x202f), + SGP_CMD_GET_SERIAL_ID = SGP_CMD(0x3682), + + SGP30_CMD_MEASURE_SIGNAL = SGP_CMD(0x2050), + + SGPC3_CMD_MEASURE_RAW = SGP_CMD(0x2046), +}; + +struct sgp_version { + u8 major; + u8 minor; +}; + +struct sgp_crc_word { + __be16 value; + u8 crc8; +} __attribute__((__packed__)); + +union sgp_reading { + u8 start; + struct sgp_crc_word raw_words[4]; +}; + +enum _iaq_buffer_state { + IAQ_BUFFER_EMPTY = 0, + IAQ_BUFFER_DEFAULT_VALS, + IAQ_BUFFER_VALID, +}; + +struct sgp_data { + struct i2c_client *client; + struct task_struct *iaq_thread; + struct mutex data_lock; + unsigned long iaq_init_start_jiffies; + unsigned long iaq_defval_skip_jiffies; + u16 product_id; + u16 feature_set; + unsigned long measure_interval_jiffies; + enum sgp_cmd iaq_init_cmd; + enum sgp_cmd measure_iaq_cmd; + enum sgp_cmd measure_gas_signals_cmd; + union sgp_reading buffer; + union sgp_reading iaq_buffer; + enum _iaq_buffer_state iaq_buffer_state; +}; + +struct sgp_device { + const struct iio_chan_spec *channels; + int num_channels; +}; + +static const struct sgp_version supported_versions_sgp30[] = { + { + .major = 1, + .minor = 0, + }, +}; + +static const struct sgp_version supported_versions_sgpc3[] = { + { + .major = 0, + .minor = 4, + }, +}; + +static const struct iio_chan_spec sgp30_channels[] = { + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_VOC, + .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .address = SGP30_IAQ_TVOC_IDX, + }, + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_CO2, + .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .address = SGP30_IAQ_CO2EQ_IDX, + }, + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_ETHANOL, + .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .address = SGP30_SIG_ETOH_IDX, + }, + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_H2, + .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .address = SGP30_SIG_H2_IDX, + }, +}; + +static const struct iio_chan_spec sgpc3_channels[] = { + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_VOC, + .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .address = SGPC3_IAQ_TVOC_IDX, + }, + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_ETHANOL, + .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .address = SGPC3_SIG_ETOH_IDX, + }, +}; + +static const struct sgp_device sgp_devices[] = { + [SGP30] = { + .channels = sgp30_channels, + .num_channels = ARRAY_SIZE(sgp30_channels), + }, + [SGPC3] = { + .channels = sgpc3_channels, + .num_channels = ARRAY_SIZE(sgpc3_channels), + }, +}; + +/** + * sgp_verify_buffer() - verify the checksums of the data buffer words + * + * @data: SGP data + * @buf: Raw data buffer + * @word_count: Num data words stored in the buffer, excluding CRC bytes + * + * Return: 0 on success, negative error otherwise. + */ +static int sgp_verify_buffer(const struct sgp_data *data, + union sgp_reading *buf, size_t word_count) +{ + size_t size = word_count * (SGP_WORD_LEN + SGP_CRC8_LEN); + int i; + u8 crc; + u8 *data_buf = &buf->start; + + for (i = 0; i < size; i += SGP_WORD_LEN + SGP_CRC8_LEN) { + crc = crc8(sgp_crc8_table, &data_buf[i], SGP_WORD_LEN, + SGP_CRC8_INIT); + if (crc != data_buf[i + SGP_WORD_LEN]) { + dev_err(&data->client->dev, "CRC error\n"); + return -EIO; + } + } + + return 0; +} + +/** + * sgp_read_cmd() - reads data from sensor after issuing a command + * The caller must hold data->data_lock for the duration of the call. + * @data: SGP data + * @cmd: SGP Command to issue + * @buf: Raw data buffer to use + * @word_count: Num words to read, excluding CRC bytes + * + * Return: 0 on success, negative error otherwise. + */ +static int sgp_read_cmd(struct sgp_data *data, enum sgp_cmd cmd, + union sgp_reading *buf, size_t word_count, + unsigned long duration_us) +{ + int ret; + struct i2c_client *client = data->client; + size_t size = word_count * (SGP_WORD_LEN + SGP_CRC8_LEN); + u8 *data_buf; + + ret = i2c_master_send(client, (const char *)&cmd, SGP_CMD_LEN); + if (ret != SGP_CMD_LEN) + return -EIO; + usleep_range(duration_us, duration_us + 1000); + + if (word_count == 0) + return 0; + + data_buf = &buf->start; + ret = i2c_master_recv(client, data_buf, size); + if (ret < 0) + return ret; + if (ret != size) + return -EIO; + + return sgp_verify_buffer(data, buf, word_count); +} + +/** + * sgp_measure_iaq() - measure and retrieve IAQ values from sensor + * The caller must hold data->data_lock for the duration of the call. + * @data: SGP data + * + * Return: 0 on success, -EBUSY on default values, negative error + * otherwise. + */ + +static int sgp_measure_iaq(struct sgp_data *data) +{ + int ret; + /* data contains default values */ + bool default_vals = !time_after(jiffies, data->iaq_init_start_jiffies + + data->iaq_defval_skip_jiffies); + + ret = sgp_read_cmd(data, data->measure_iaq_cmd, &data->iaq_buffer, + SGP_MEASUREMENT_LEN, SGP_MEASUREMENT_DURATION_US); + if (ret < 0) + return ret; + + data->iaq_buffer_state = IAQ_BUFFER_DEFAULT_VALS; + + if (default_vals) + return -EBUSY; + + data->iaq_buffer_state = IAQ_BUFFER_VALID; + + return 0; +} + +static void sgp_iaq_thread_sleep_until(const struct sgp_data *data, + unsigned long sleep_jiffies) +{ + const long IAQ_POLL = 50000; + + while (!time_after(jiffies, sleep_jiffies)) { + usleep_range(IAQ_POLL, IAQ_POLL + 10000); + if (kthread_should_stop() || data->iaq_init_start_jiffies == 0) + return; + } +} + +static int sgp_iaq_threadfn(void *p) +{ + struct sgp_data *data = (struct sgp_data *)p; + unsigned long next_update_jiffies; + int ret; + + while (!kthread_should_stop()) { + mutex_lock(&data->data_lock); + if (data->iaq_init_start_jiffies == 0) { + ret = sgp_read_cmd(data, data->iaq_init_cmd, NULL, 0, + SGP_CMD_DURATION_US); + if (ret < 0) + goto unlock_sleep_continue; + data->iaq_init_start_jiffies = jiffies; + } + + ret = sgp_measure_iaq(data); + if (ret && ret != -EBUSY) { + dev_warn(&data->client->dev, + "IAQ measurement error [%d]\n", ret); + } +unlock_sleep_continue: + next_update_jiffies = jiffies + data->measure_interval_jiffies; + mutex_unlock(&data->data_lock); + sgp_iaq_thread_sleep_until(data, next_update_jiffies); + } + + return 0; +} + +static int sgp_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct sgp_data *data = iio_priv(indio_dev); + struct sgp_crc_word *words; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + mutex_lock(&data->data_lock); + if (data->iaq_buffer_state != IAQ_BUFFER_VALID) { + mutex_unlock(&data->data_lock); + return -EBUSY; + } + words = data->iaq_buffer.raw_words; + switch (chan->address) { + case SGP30_IAQ_TVOC_IDX: + case SGPC3_IAQ_TVOC_IDX: + *val = 0; + *val2 = be16_to_cpu(words[1].value); + ret = IIO_VAL_INT_PLUS_NANO; + break; + case SGP30_IAQ_CO2EQ_IDX: + *val = 0; + *val2 = be16_to_cpu(words[0].value); + ret = IIO_VAL_INT_PLUS_MICRO; + break; + default: + ret = -EINVAL; + break; + } + mutex_unlock(&data->data_lock); + break; + case IIO_CHAN_INFO_RAW: + mutex_lock(&data->data_lock); + if (chan->address == SGPC3_SIG_ETOH_IDX) { + if (data->iaq_buffer_state == IAQ_BUFFER_EMPTY) + ret = -EBUSY; + else + ret = 0; + words = data->iaq_buffer.raw_words; + } else { + ret = sgp_read_cmd(data, data->measure_gas_signals_cmd, + &data->buffer, SGP_MEASUREMENT_LEN, + SGP_MEASUREMENT_DURATION_US); + words = data->buffer.raw_words; + } + if (ret) { + mutex_unlock(&data->data_lock); + return ret; + } + + switch (chan->address) { + case SGP30_SIG_ETOH_IDX: + *val = be16_to_cpu(words[1].value); + ret = IIO_VAL_INT; + break; + case SGPC3_SIG_ETOH_IDX: + case SGP30_SIG_H2_IDX: + *val = be16_to_cpu(words[0].value); + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + break; + } + mutex_unlock(&data->data_lock); + break; + default: + return -EINVAL; + } + + return ret; +} + +static int sgp_check_compat(struct sgp_data *data, + unsigned int product_id) +{ + const struct sgp_version *supported_versions; + u16 ix, num_fs; + u16 product, generation, major, minor; + + /* driver does not match product */ + generation = SGP_VERS_GEN(data); + if (generation != 0) { + dev_err(&data->client->dev, + "incompatible product generation %d != 0", generation); + return -ENODEV; + } + + product = SGP_VERS_PRODUCT(data); + if (product != product_id) { + dev_err(&data->client->dev, + "sensor reports a different product: 0x%04hx\n", + product); + return -ENODEV; + } + + if (SGP_VERS_RESERVED(data)) + dev_warn(&data->client->dev, "reserved bit is set\n"); + + /* engineering samples are not supported: no interface guarantees */ + if (SGP_VERS_ENG_BIT(data)) + return -ENODEV; + + switch (product) { + case SGP30: + supported_versions = supported_versions_sgp30; + num_fs = ARRAY_SIZE(supported_versions_sgp30); + break; + case SGPC3: + supported_versions = supported_versions_sgpc3; + num_fs = ARRAY_SIZE(supported_versions_sgpc3); + break; + default: + return -ENODEV; + } + + major = SGP_VERS_MAJOR(data); + minor = SGP_VERS_MINOR(data); + for (ix = 0; ix < num_fs; ix++) { + if (major == supported_versions[ix].major && + minor >= supported_versions[ix].minor) + return 0; + } + dev_err(&data->client->dev, "unsupported sgp version: %d.%d\n", + major, minor); + + return -ENODEV; +} + +static void sgp_init(struct sgp_data *data) +{ + data->iaq_init_cmd = SGP_CMD_IAQ_INIT; + data->iaq_init_start_jiffies = 0; + data->iaq_buffer_state = IAQ_BUFFER_EMPTY; + switch (SGP_VERS_PRODUCT(data)) { + case SGP30: + data->measure_interval_jiffies = SGP30_MEASURE_INTERVAL_HZ * HZ; + data->measure_iaq_cmd = SGP_CMD_IAQ_MEASURE; + data->measure_gas_signals_cmd = SGP30_CMD_MEASURE_SIGNAL; + data->product_id = SGP30; + data->iaq_defval_skip_jiffies = 15 * HZ; + break; + case SGPC3: + data->measure_interval_jiffies = SGPC3_MEASURE_INTERVAL_HZ * HZ; + data->measure_iaq_cmd = SGPC3_CMD_MEASURE_RAW; + data->measure_gas_signals_cmd = SGPC3_CMD_MEASURE_RAW; + data->product_id = SGPC3; + data->iaq_defval_skip_jiffies = + 43 * data->measure_interval_jiffies; + break; + }; +} + +static const struct iio_info sgp_info = { + .read_raw = sgp_read_raw, +}; + +static const struct of_device_id sgp_dt_ids[] = { + { .compatible = "sensirion,sgp30", .data = (void *)SGP30 }, + { .compatible = "sensirion,sgpc3", .data = (void *)SGPC3 }, + { } +}; + +static int sgp_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct sgp_data *data; + const struct of_device_id *of_id; + unsigned long product_id; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + of_id = of_match_device(sgp_dt_ids, &client->dev); + if (of_id) + product_id = (unsigned long)of_id->data; + else + product_id = id->driver_data; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + crc8_populate_msb(sgp_crc8_table, SGP_CRC8_POLYNOMIAL); + mutex_init(&data->data_lock); + + /* get feature set version and write it to client data */ + ret = sgp_read_cmd(data, SGP_CMD_GET_FEATURE_SET, &data->buffer, 1, + SGP_CMD_DURATION_US); + if (ret < 0) + return ret; + + data->feature_set = be16_to_cpu(data->buffer.raw_words[0].value); + + ret = sgp_check_compat(data, product_id); + if (ret) + return ret; + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &sgp_info; + indio_dev->name = id->name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = sgp_devices[product_id].channels; + indio_dev->num_channels = sgp_devices[product_id].num_channels; + + sgp_init(data); + + ret = devm_iio_device_register(&client->dev, indio_dev); + if (ret) { + dev_err(&client->dev, "failed to register iio device\n"); + return ret; + } + + data->iaq_thread = kthread_run(sgp_iaq_threadfn, data, + "%s-iaq", data->client->name); + + return 0; +} + +static int sgp_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct sgp_data *data = iio_priv(indio_dev); + + if (data->iaq_thread) + kthread_stop(data->iaq_thread); + + return 0; +} + +static const struct i2c_device_id sgp_id[] = { + { "sgp30", SGP30 }, + { "sgpc3", SGPC3 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, sgp_id); +MODULE_DEVICE_TABLE(of, sgp_dt_ids); + +static struct i2c_driver sgp_driver = { + .driver = { + .name = "sgp30", + .of_match_table = of_match_ptr(sgp_dt_ids), + }, + .probe = sgp_probe, + .remove = sgp_remove, + .id_table = sgp_id, +}; +module_i2c_driver(sgp_driver); + +MODULE_AUTHOR("Andreas Brauchli "); +MODULE_AUTHOR("Pascal Sachs "); +MODULE_DESCRIPTION("Sensirion SGP gas sensors"); +MODULE_LICENSE("GPL v2"); -- cgit From 4535fa0576d2bb14060a7e80a710382414a93558 Mon Sep 17 00:00:00 2001 From: Andreas Brauchli Date: Thu, 13 Dec 2018 15:44:18 +0100 Subject: iio: chemical: sgp30: add device tree support Add device tree support for Sensirion SGP30/SGPC3 gas sensors. Signed-off-by: Andreas Brauchli Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/chemical/sensirion,sgp30.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/chemical/sensirion,sgp30.txt diff --git a/Documentation/devicetree/bindings/iio/chemical/sensirion,sgp30.txt b/Documentation/devicetree/bindings/iio/chemical/sensirion,sgp30.txt new file mode 100644 index 000000000000..5844ed58173c --- /dev/null +++ b/Documentation/devicetree/bindings/iio/chemical/sensirion,sgp30.txt @@ -0,0 +1,15 @@ +* Sensirion SGP30/SGPC3 multi-pixel Gas Sensor + +Required properties: + + - compatible: must be one of + "sensirion,sgp30" + "sensirion,sgpc3" + - reg: the I2C address of the sensor + +Example: + +gas@58 { + compatible = "sensirion,sgp30"; + reg = <0x58>; +}; -- cgit From 557e585c3fdba1f6cddb4516a82da53b52fd9963 Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Thu, 13 Dec 2018 14:46:15 +0200 Subject: staging: iio: adc: ad7606: Use wait-for-completion handler This patch replaces the use of wait_event_interruptible() with wait_for_completion_timeout() when reading the result of a single conversion. In this way, if the interrupt never occurs, the program will not remain blocked. Signed-off-by: Stefan Popa Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.c | 14 +++++++------- drivers/staging/iio/adc/ad7606.h | 6 ++---- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/staging/iio/adc/ad7606.c index 7308fa8fbb4c..379a99ed22af 100644 --- a/drivers/staging/iio/adc/ad7606.c +++ b/drivers/staging/iio/adc/ad7606.c @@ -119,12 +119,13 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch) struct ad7606_state *st = iio_priv(indio_dev); int ret; - st->done = false; gpiod_set_value(st->gpio_convst, 1); - - ret = wait_event_interruptible(st->wq_data_avail, st->done); - if (ret) + ret = wait_for_completion_timeout(&st->completion, + msecs_to_jiffies(1000)); + if (!ret) { + ret = -ETIMEDOUT; goto error_ret; + } ret = ad7606_read_samples(st); if (ret == 0) @@ -389,8 +390,7 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id) if (iio_buffer_enabled(indio_dev)) { schedule_work(&st->poll_work); } else { - st->done = true; - wake_up_interruptible(&st->wq_data_avail); + complete(&st->completion); } return IRQ_HANDLED; @@ -474,7 +474,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, indio_dev->channels = st->chip_info->channels; indio_dev->num_channels = st->chip_info->num_channels; - init_waitqueue_head(&st->wq_data_avail); + init_completion(&st->completion); ret = ad7606_reset(st); if (ret) diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index 86188054b60b..a46843f96e0c 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -29,11 +29,9 @@ struct ad7606_chip_info { * @reg regulator info for the the power supply of the device * @poll_work work struct for continuously reading data from the device * into an IIO triggered buffer - * @wq_data_avail wait queue struct for buffer mode * @bops bus operations (SPI or parallel) * @range voltage range selection, selects which scale to apply * @oversampling oversampling selection - * @done marks whether reading data is done * @base_address address from where to read data in parallel operation * @lock protect sensor state from concurrent accesses to GPIOs * @gpio_convst GPIO descriptor for conversion start signal (CONVST) @@ -44,6 +42,7 @@ struct ad7606_chip_info { * @gpio_frstdata GPIO descriptor for reading from device when data * is being read on the first channel * @gpio_os GPIO descriptors to control oversampling on the device + * @complete completion to indicate end of conversion * @data buffer for reading data from the device */ @@ -52,11 +51,9 @@ struct ad7606_state { const struct ad7606_chip_info *chip_info; struct regulator *reg; struct work_struct poll_work; - wait_queue_head_t wq_data_avail; const struct ad7606_bus_ops *bops; unsigned int range; unsigned int oversampling; - bool done; void __iomem *base_address; struct mutex lock; /* protect sensor state */ @@ -66,6 +63,7 @@ struct ad7606_state { struct gpio_desc *gpio_standby; struct gpio_desc *gpio_frstdata; struct gpio_descs *gpio_os; + struct completion completion; /* * DMA (thus cache coherency maintenance) requires the -- cgit From c0683bfd3772337353e95decc2bf0421058088f7 Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Thu, 13 Dec 2018 14:46:16 +0200 Subject: staging: iio: adc: ad7606: Use devm functions in probe Switch to devm version of request_irq, iio_triggered_buffer_setup, iio_device_register. To avoid potential ordering issues in probe, devm_add_action_or_reset() is used for the regulator_disable(). This simplifies the code and decreases the chance of bugs. Signed-off-by: Stefan Popa Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.c | 59 +++++++++++++----------------------- drivers/staging/iio/adc/ad7606.h | 1 - drivers/staging/iio/adc/ad7606_par.c | 6 ---- drivers/staging/iio/adc/ad7606_spi.c | 6 ---- 4 files changed, 21 insertions(+), 51 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/staging/iio/adc/ad7606.c index 379a99ed22af..36ca75a9907b 100644 --- a/drivers/staging/iio/adc/ad7606.c +++ b/drivers/staging/iio/adc/ad7606.c @@ -418,6 +418,13 @@ static const struct iio_info ad7606_info_range = { .attrs = &ad7606_attribute_group_range, }; +static void ad7606_regulator_disable(void *data) +{ + struct ad7606_state *st = data; + + regulator_disable(st->reg); +} + int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, const char *name, unsigned int id, const struct ad7606_bus_ops *bops) @@ -431,6 +438,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, return -ENOMEM; st = iio_priv(indio_dev); + dev_set_drvdata(dev, indio_dev); st->dev = dev; mutex_init(&st->lock); @@ -451,11 +459,15 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, return ret; } + ret = devm_add_action_or_reset(dev, ad7606_regulator_disable, st); + if (ret) + return ret; + st->chip_info = &ad7606_chip_info_tbl[id]; ret = ad7606_request_gpios(st); if (ret) - goto error_disable_reg; + return ret; indio_dev->dev.parent = dev; if (st->gpio_os) { @@ -480,50 +492,21 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, if (ret) dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); - ret = request_irq(irq, ad7606_interrupt, IRQF_TRIGGER_FALLING, name, - indio_dev); - if (ret) - goto error_disable_reg; - - ret = iio_triggered_buffer_setup(indio_dev, &ad7606_trigger_handler, - NULL, NULL); + ret = devm_request_irq(dev, irq, ad7606_interrupt, IRQF_TRIGGER_FALLING, + name, indio_dev); if (ret) - goto error_free_irq; + return ret; - ret = iio_device_register(indio_dev); + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + &ad7606_trigger_handler, + NULL, NULL); if (ret) - goto error_unregister_ring; - - dev_set_drvdata(dev, indio_dev); - - return 0; -error_unregister_ring: - iio_triggered_buffer_cleanup(indio_dev); - -error_free_irq: - free_irq(irq, indio_dev); + return ret; -error_disable_reg: - regulator_disable(st->reg); - return ret; + return devm_iio_device_register(dev, indio_dev); } EXPORT_SYMBOL_GPL(ad7606_probe); -int ad7606_remove(struct device *dev, int irq) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7606_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - free_irq(irq, indio_dev); - regulator_disable(st->reg); - - return 0; -} -EXPORT_SYMBOL_GPL(ad7606_remove); - #ifdef CONFIG_PM_SLEEP static int ad7606_suspend(struct device *dev) diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index a46843f96e0c..510a93db362f 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -85,7 +85,6 @@ struct ad7606_bus_ops { int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, const char *name, unsigned int id, const struct ad7606_bus_ops *bops); -int ad7606_remove(struct device *dev, int irq); enum ad7606_supported_device_ids { ID_AD7605_4, diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index 8bd86e727b02..c04ce8ac97ff 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -72,11 +72,6 @@ static int ad7606_par_probe(struct platform_device *pdev) &ad7606_par8_bops); } -static int ad7606_par_remove(struct platform_device *pdev) -{ - return ad7606_remove(&pdev->dev, platform_get_irq(pdev, 0)); -} - static const struct platform_device_id ad7606_driver_ids[] = { { .name = "ad7605-4", @@ -98,7 +93,6 @@ MODULE_DEVICE_TABLE(platform, ad7606_driver_ids); static struct platform_driver ad7606_driver = { .probe = ad7606_par_probe, - .remove = ad7606_par_remove, .id_table = ad7606_driver_ids, .driver = { .name = "ad7606", diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index b76ca5a8c059..f38594f38a31 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -49,11 +49,6 @@ static int ad7606_spi_probe(struct spi_device *spi) &ad7606_spi_bops); } -static int ad7606_spi_remove(struct spi_device *spi) -{ - return ad7606_remove(&spi->dev, spi->irq); -} - static const struct spi_device_id ad7606_id[] = { {"ad7605-4", ID_AD7605_4}, {"ad7606-8", ID_AD7606_8}, @@ -69,7 +64,6 @@ static struct spi_driver ad7606_driver = { .pm = AD7606_PM_OPS, }, .probe = ad7606_spi_probe, - .remove = ad7606_spi_remove, .id_table = ad7606_id, }; module_spi_driver(ad7606_driver); -- cgit From 41f71e5e7dafb4608834d6e3be49b5568639c0c1 Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Thu, 13 Dec 2018 14:46:18 +0200 Subject: staging: iio: adc: ad7606: Use find_closest() macro When looking for the available scale or oversampling ratio, it is better to use the find_closest() macro. This simplifies the code and also does not require an exact value to be entered from the user space. Signed-off-by: Stefan Popa Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.c | 58 +++++++++++++++------------------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/staging/iio/adc/ad7606.c index 36ca75a9907b..d032590739e8 100644 --- a/drivers/staging/iio/adc/ad7606.c +++ b/drivers/staging/iio/adc/ad7606.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -30,8 +31,12 @@ * Scales are computed as 5000/32768 and 10000/32768 respectively, * so that when applied to the raw values they provide mV values */ -static const unsigned int scale_avail[2][2] = { - {0, 152588}, {0, 305176} +static const unsigned int scale_avail[2] = { + 152588, 305176 +}; + +static const unsigned int ad7606_oversampling_avail[7] = { + 1, 2, 4, 8, 16, 32, 64, }; static int ad7606_reset(struct ad7606_state *st) @@ -160,8 +165,8 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, *val = (short)ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val = scale_avail[st->range][0]; - *val2 = scale_avail[st->range][1]; + *val = 0; + *val2 = scale_avail[st->range]; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: *val = st->oversampling; @@ -177,8 +182,8 @@ static ssize_t in_voltage_scale_available_show(struct device *dev, int i, len = 0; for (i = 0; i < ARRAY_SIZE(scale_avail); i++) - len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06u ", - scale_avail[i][0], scale_avail[i][1]); + len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", + scale_avail[i]); buf[len - 1] = '\n'; @@ -187,18 +192,6 @@ static ssize_t in_voltage_scale_available_show(struct device *dev, static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0); -static int ad7606_oversampling_get_index(unsigned int val) -{ - unsigned char supported[] = {1, 2, 4, 8, 16, 32, 64}; - int i; - - for (i = 0; i < ARRAY_SIZE(supported); i++) - if (val == supported[i]) - return i; - - return -EINVAL; -} - static int ad7606_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, @@ -207,36 +200,29 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, { struct ad7606_state *st = iio_priv(indio_dev); DECLARE_BITMAP(values, 3); - int ret, i; + int i; switch (mask) { case IIO_CHAN_INFO_SCALE: - ret = -EINVAL; mutex_lock(&st->lock); - for (i = 0; i < ARRAY_SIZE(scale_avail); i++) - if (val2 == scale_avail[i][1]) { - gpiod_set_value(st->gpio_range, i); - st->range = i; - - ret = 0; - break; - } + i = find_closest(val2, scale_avail, ARRAY_SIZE(scale_avail)); + gpiod_set_value(st->gpio_range, i); + st->range = i; mutex_unlock(&st->lock); - return ret; + return 0; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: if (val2) return -EINVAL; - ret = ad7606_oversampling_get_index(val); - if (ret < 0) - return ret; + i = find_closest(val, ad7606_oversampling_avail, + ARRAY_SIZE(ad7606_oversampling_avail)); - values[0] = ret; + values[0] = i; mutex_lock(&st->lock); - gpiod_set_array_value(3, st->gpio_os->desc, st->gpio_os->info, - values); - st->oversampling = val; + gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, + st->gpio_os->info, values); + st->oversampling = ad7606_oversampling_avail[i]; mutex_unlock(&st->lock); return 0; -- cgit From 6620585a0c9ee75332346ef2dcb1c4a7573db57b Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Thu, 13 Dec 2018 14:46:19 +0200 Subject: staging: iio: adc: ad7606: Use vendor prefix for DT properties The 'adi' vendor prefix needs to be added to conversion-start, range, first-data and oversampling-ratio properties. Signed-off-by: Stefan Popa Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/staging/iio/adc/ad7606.c index d032590739e8..e1d85b7a0e4c 100644 --- a/drivers/staging/iio/adc/ad7606.c +++ b/drivers/staging/iio/adc/ad7606.c @@ -334,7 +334,7 @@ static int ad7606_request_gpios(struct ad7606_state *st) { struct device *dev = st->dev; - st->gpio_convst = devm_gpiod_get(dev, "conversion-start", + st->gpio_convst = devm_gpiod_get(dev, "adi,conversion-start", GPIOD_OUT_LOW); if (IS_ERR(st->gpio_convst)) return PTR_ERR(st->gpio_convst); @@ -343,7 +343,8 @@ static int ad7606_request_gpios(struct ad7606_state *st) if (IS_ERR(st->gpio_reset)) return PTR_ERR(st->gpio_reset); - st->gpio_range = devm_gpiod_get_optional(dev, "range", GPIOD_OUT_LOW); + st->gpio_range = devm_gpiod_get_optional(dev, "adi,range", + GPIOD_OUT_LOW); if (IS_ERR(st->gpio_range)) return PTR_ERR(st->gpio_range); @@ -352,7 +353,7 @@ static int ad7606_request_gpios(struct ad7606_state *st) if (IS_ERR(st->gpio_standby)) return PTR_ERR(st->gpio_standby); - st->gpio_frstdata = devm_gpiod_get_optional(dev, "first-data", + st->gpio_frstdata = devm_gpiod_get_optional(dev, "adi,first-data", GPIOD_IN); if (IS_ERR(st->gpio_frstdata)) return PTR_ERR(st->gpio_frstdata); @@ -360,7 +361,8 @@ static int ad7606_request_gpios(struct ad7606_state *st) if (!st->chip_info->has_oversampling) return 0; - st->gpio_os = devm_gpiod_get_array_optional(dev, "oversampling-ratio", + st->gpio_os = devm_gpiod_get_array_optional(dev, + "adi,oversampling-ratio", GPIOD_OUT_LOW); return PTR_ERR_OR_ZERO(st->gpio_os); } -- cgit From 43f9b204edf033b6fb87f761c70a8f55462983ae Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Thu, 13 Dec 2018 14:46:20 +0200 Subject: staging: iio: adc: ad7606: Add OF device ID table The driver does not have a struct of_device_id table, but supported devices are registered via Device Trees. This patch adds and OF device ID table. Signed-off-by: Stefan Popa Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606_par.c | 10 ++++++++++ drivers/staging/iio/adc/ad7606_spi.c | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index c04ce8ac97ff..da26742e8b46 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -91,12 +91,22 @@ static const struct platform_device_id ad7606_driver_ids[] = { MODULE_DEVICE_TABLE(platform, ad7606_driver_ids); +static const struct of_device_id ad7606_of_match[] = { + { .compatible = "adi,ad7605-4" }, + { .compatible = "adi,ad7606-4" }, + { .compatible = "adi,ad7606-6" }, + { .compatible = "adi,ad7606-8" }, + { }, +}; +MODULE_DEVICE_TABLE(of, ad7606_of_match); + static struct platform_driver ad7606_driver = { .probe = ad7606_par_probe, .id_table = ad7606_driver_ids, .driver = { .name = "ad7606", .pm = AD7606_PM_OPS, + .of_match_table = ad7606_of_match, }, }; diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index f38594f38a31..e533917db094 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -58,9 +58,19 @@ static const struct spi_device_id ad7606_id[] = { }; MODULE_DEVICE_TABLE(spi, ad7606_id); +static const struct of_device_id ad7606_of_match[] = { + { .compatible = "adi,ad7605-4" }, + { .compatible = "adi,ad7606-4" }, + { .compatible = "adi,ad7606-6" }, + { .compatible = "adi,ad7606-8" }, + { }, +}; +MODULE_DEVICE_TABLE(of, ad7606_of_match); + static struct spi_driver ad7606_driver = { .driver = { .name = "ad7606", + .of_match_table = ad7606_of_match, .pm = AD7606_PM_OPS, }, .probe = ad7606_spi_probe, -- cgit From 6a4b8937a3d6238b5aa9b9c8083f7238903bfb86 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 15 Dec 2018 06:31:24 +0000 Subject: iio: imu: st_lsm6dsx: remove set but not used variable '' Fixes gcc '-Wunused-but-set-variable' warning: drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c: In function 'st_lsm6dsx_shub_read_reg': drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c:108:41: warning: variable 'hub_settings' set but not used [-Wunused-but-set-variable] It never used since introduction in commit c91c1c844ebd ("iio: imu: st_lsm6dsx: add i2c embedded controller support") Signed-off-by: YueHaibing Acked-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c index 8e47dccdd40f..66fbcd94642d 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c @@ -105,12 +105,10 @@ static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw) static int st_lsm6dsx_shub_read_reg(struct st_lsm6dsx_hw *hw, u8 addr, u8 *data, int len) { - const struct st_lsm6dsx_shub_settings *hub_settings; int err; mutex_lock(&hw->page_lock); - hub_settings = &hw->settings->shub_settings; err = st_lsm6dsx_set_page(hw, true); if (err < 0) goto out; -- cgit From c546d49656143855093c7b7fde60866e6e23a69d Mon Sep 17 00:00:00 2001 From: Tomasz Duszynski Date: Tue, 18 Dec 2018 21:28:09 +0100 Subject: iio: chemical: sps30: add support for self cleaning Self cleaning is especially useful in cases where sensor undergoes frequent power on/off cycles. In such scenarios it is recommended to turn self cleaning at least once per week in order to maintain reliable measurements. Self cleaning is activated by writing 1 to a dedicated attribute. Internal fan accelerates to its maximum speed and keeps spinning for about 10 seconds blowing out accumulated dust. Signed-off-by: Tomasz Duszynski Tested-by: Andreas Brauchli Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio-sps30 | 8 ++++++ drivers/iio/chemical/sps30.c | 35 ++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-sps30 diff --git a/Documentation/ABI/testing/sysfs-bus-iio-sps30 b/Documentation/ABI/testing/sysfs-bus-iio-sps30 new file mode 100644 index 000000000000..e7ce2c57635e --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-sps30 @@ -0,0 +1,8 @@ +What: /sys/bus/iio/devices/iio:deviceX/start_cleaning +Date: December 2018 +KernelVersion: 4.22 +Contact: linux-iio@vger.kernel.org +Description: + Writing 1 starts sensor self cleaning. Internal fan accelerates + to its maximum speed and keeps spinning for about 10 seconds in + order to blow out accumulated dust. diff --git a/drivers/iio/chemical/sps30.c b/drivers/iio/chemical/sps30.c index fa3cd409b90b..f3b4390c8f5c 100644 --- a/drivers/iio/chemical/sps30.c +++ b/drivers/iio/chemical/sps30.c @@ -7,7 +7,6 @@ * I2C slave address: 0x69 * * TODO: - * - support for turning on fan cleaning * - support for reading/setting auto cleaning interval */ @@ -37,6 +36,7 @@ #define SPS30_READ_DATA_READY_FLAG 0x0202 #define SPS30_READ_DATA 0x0300 #define SPS30_READ_SERIAL 0xd033 +#define SPS30_START_FAN_CLEANING 0x5607 enum { PM1, @@ -104,6 +104,7 @@ static int sps30_do_cmd(struct sps30_state *state, u16 cmd, u8 *data, int size) break; case SPS30_STOP_MEAS: case SPS30_RESET: + case SPS30_START_FAN_CLEANING: ret = sps30_write_then_read(state, buf, 2, NULL, 0); break; case SPS30_READ_DATA_READY_FLAG: @@ -275,7 +276,39 @@ static int sps30_read_raw(struct iio_dev *indio_dev, return -EINVAL; } +static ssize_t start_cleaning_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct sps30_state *state = iio_priv(indio_dev); + int val, ret; + + if (kstrtoint(buf, 0, &val) || val != 1) + return -EINVAL; + + mutex_lock(&state->lock); + ret = sps30_do_cmd(state, SPS30_START_FAN_CLEANING, NULL, 0); + mutex_unlock(&state->lock); + if (ret) + return ret; + + return len; +} + +static IIO_DEVICE_ATTR_WO(start_cleaning, 0); + +static struct attribute *sps30_attrs[] = { + &iio_dev_attr_start_cleaning.dev_attr.attr, + NULL +}; + +static const struct attribute_group sps30_attr_group = { + .attrs = sps30_attrs, +}; + static const struct iio_info sps30_info = { + .attrs = &sps30_attr_group, .read_raw = sps30_read_raw, }; -- cgit From ae0b3773721f08526c850e2d8dec85bdb870cd12 Mon Sep 17 00:00:00 2001 From: Kangjie Lu Date: Thu, 20 Dec 2018 01:21:22 -0600 Subject: iio: ad9523: fix a missing check of return value If ad9523_write() fails, indio_dev may get incorrect data. The fix inserts a check for the return value of ad9523_write(), and it fails, returns an error. Signed-off-by: Kangjie Lu Signed-off-by: Jonathan Cameron --- drivers/iio/frequency/ad9523.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c index f3f94fbdd20a..3f9be69499ec 100644 --- a/drivers/iio/frequency/ad9523.c +++ b/drivers/iio/frequency/ad9523.c @@ -943,11 +943,14 @@ static int ad9523_setup(struct iio_dev *indio_dev) } } - for_each_clear_bit(i, &active_mask, AD9523_NUM_CHAN) - ad9523_write(indio_dev, + for_each_clear_bit(i, &active_mask, AD9523_NUM_CHAN) { + ret = ad9523_write(indio_dev, AD9523_CHANNEL_CLOCK_DIST(i), AD9523_CLK_DIST_DRIVER_MODE(TRISTATE) | AD9523_CLK_DIST_PWR_DOWN_EN); + if (ret < 0) + return ret; + } ret = ad9523_write(indio_dev, AD9523_POWER_DOWN_CTRL, 0); if (ret < 0) -- cgit From 2bbf53e3e50661c0383048b86a387f74ce6b023c Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Mon, 17 Dec 2018 14:23:35 +0200 Subject: staging: iio: adc: ad7606: Simplify the Kconfing menu There is no point in having three menu entries that can be selected individually. Instead, the SPI and parallel interfaces should select AD7606. Signed-off-by: Stefan Popa Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/Kconfig | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index fc23059f1673..302639ab9c89 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -4,35 +4,28 @@ menu "Analog to digital converters" config AD7606 - tristate "Analog Devices AD7606 ADC driver" - depends on GPIOLIB || COMPILE_TEST - depends on HAS_IOMEM + tristate select IIO_BUFFER select IIO_TRIGGERED_BUFFER - help - Say yes here to build support for Analog Devices: - ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). - - To compile this driver as a module, choose M here: the - module will be called ad7606. config AD7606_IFACE_PARALLEL - tristate "parallel interface support" - depends on AD7606 + tristate "Analog Devices AD7606 ADC driver with parallel interface support" + depends on HAS_IOMEM + select AD7606 help - Say yes here to include parallel interface support on the AD7606 - ADC driver. + Say yes here to build parallel interface support for Analog Devices: + ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). To compile this driver as a module, choose M here: the module will be called ad7606_parallel. config AD7606_IFACE_SPI - tristate "spi interface support" - depends on AD7606 + tristate "Analog Devices AD7606 ADC driver with spi interface support" depends on SPI + select AD7606 help - Say yes here to include parallel interface support on the AD7606 - ADC driver. + Say yes here to build spi interface support for Analog Devices: + ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). To compile this driver as a module, choose M here: the module will be called ad7606_spi. -- cgit From ca5b4637d7ca561dbaba13d725957610a783ac2c Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Mon, 17 Dec 2018 14:23:36 +0200 Subject: staging: iio: adc: ad7606: Use SPDX identifier This patch replaces the license text at the top of ad7606 driver files and instead adds SPDX GPL-2.0 license identifier. Signed-off-by: Stefan Popa Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.c | 3 +-- drivers/staging/iio/adc/ad7606.h | 3 +-- drivers/staging/iio/adc/ad7606_par.c | 3 +-- drivers/staging/iio/adc/ad7606_spi.c | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/staging/iio/adc/ad7606.c index e1d85b7a0e4c..8a34efa6c0f8 100644 --- a/drivers/staging/iio/adc/ad7606.c +++ b/drivers/staging/iio/adc/ad7606.c @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * AD7606 SPI ADC driver * * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. */ #include diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index 510a93db362f..3e12fff2f1ad 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -1,9 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * AD7606 ADC driver * * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. */ #ifndef IIO_ADC_AD7606_H_ diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index da26742e8b46..ae0867fd4b99 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * AD7606 Parallel Interface ADC driver * * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. */ #include diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index e533917db094..a69c26537a47 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * AD7606 SPI ADC driver * * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. */ #include -- cgit From cc49bd1652a405dc641aeffa6b0925ad9a1affb3 Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Mon, 17 Dec 2018 14:23:37 +0200 Subject: staging: iio: adc: ad7606: Add support for threaded irq This patch replaces the use of a polling ring buffer with a threaded interrupt. Enabling the buffer sets the CONVST signal to high. When the rising edge of the CONVST is applied, BUSY signal goes logic high and transitions low at the end of the entire conversion process. The falling edge of the BUSY signal triggers the interrupt. ad7606_trigger_handler() is used as bottom half of the poll function. It reads data from the device and stores it in the internal buffer. Signed-off-by: Stefan Popa Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.c | 111 +++++++++++++++++++++++++++++---------- drivers/staging/iio/adc/ad7606.h | 6 +-- 2 files changed, 84 insertions(+), 33 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/staging/iio/adc/ad7606.c index 8a34efa6c0f8..50d88571e4ac 100644 --- a/drivers/staging/iio/adc/ad7606.c +++ b/drivers/staging/iio/adc/ad7606.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "ad7606.h" @@ -86,36 +87,24 @@ static int ad7606_read_samples(struct ad7606_state *st) static irqreturn_t ad7606_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; - struct ad7606_state *st = iio_priv(pf->indio_dev); - - gpiod_set_value(st->gpio_convst, 1); - - return IRQ_HANDLED; -} - -/** - * ad7606_poll_bh_to_ring() bh of trigger launched polling to ring buffer - * @work_s: the work struct through which this was scheduled - * - * Currently there is no option in this driver to disable the saving of - * timestamps within the ring. - * I think the one copy of this at a time was to avoid problems if the - * trigger was set far too high and the reads then locked up the computer. - **/ -static void ad7606_poll_bh_to_ring(struct work_struct *work_s) -{ - struct ad7606_state *st = container_of(work_s, struct ad7606_state, - poll_work); - struct iio_dev *indio_dev = iio_priv_to_dev(st); + struct iio_dev *indio_dev = pf->indio_dev; + struct ad7606_state *st = iio_priv(indio_dev); int ret; + mutex_lock(&st->lock); + ret = ad7606_read_samples(st); if (ret == 0) iio_push_to_buffers_with_timestamp(indio_dev, st->data, iio_get_time_ns(indio_dev)); - gpiod_set_value(st->gpio_convst, 0); iio_trigger_notify_done(indio_dev->trig); + /* The rising edge of the CONVST signal starts a new conversion. */ + gpiod_set_value(st->gpio_convst, 1); + + mutex_unlock(&st->lock); + + return IRQ_HANDLED; } static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch) @@ -366,8 +355,11 @@ static int ad7606_request_gpios(struct ad7606_state *st) return PTR_ERR_OR_ZERO(st->gpio_os); } -/** - * Interrupt handler +/* + * The BUSY signal indicates when conversions are in progress, so when a rising + * edge of CONVST is applied, BUSY goes logic high and transitions low at the + * end of the entire conversion process. The falling edge of the BUSY signal + * triggers this interrupt. */ static irqreturn_t ad7606_interrupt(int irq, void *dev_id) { @@ -375,7 +367,8 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id) struct ad7606_state *st = iio_priv(indio_dev); if (iio_buffer_enabled(indio_dev)) { - schedule_work(&st->poll_work); + gpiod_set_value(st->gpio_convst, 0); + iio_trigger_poll_chained(st->trig); } else { complete(&st->completion); } @@ -383,26 +376,69 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id) return IRQ_HANDLED; }; +static int ad7606_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + if (st->trig != trig) + return -EINVAL; + + return 0; +} + +static int ad7606_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + iio_triggered_buffer_postenable(indio_dev); + gpiod_set_value(st->gpio_convst, 1); + + return 0; +} + +static int ad7606_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + gpiod_set_value(st->gpio_convst, 0); + + return iio_triggered_buffer_predisable(indio_dev); +} + +static const struct iio_buffer_setup_ops ad7606_buffer_ops = { + .postenable = &ad7606_buffer_postenable, + .predisable = &ad7606_buffer_predisable, +}; + static const struct iio_info ad7606_info_no_os_or_range = { .read_raw = &ad7606_read_raw, + .validate_trigger = &ad7606_validate_trigger, }; static const struct iio_info ad7606_info_os_and_range = { .read_raw = &ad7606_read_raw, .write_raw = &ad7606_write_raw, .attrs = &ad7606_attribute_group_os_and_range, + .validate_trigger = &ad7606_validate_trigger, }; static const struct iio_info ad7606_info_os = { .read_raw = &ad7606_read_raw, .write_raw = &ad7606_write_raw, .attrs = &ad7606_attribute_group_os, + .validate_trigger = &ad7606_validate_trigger, }; static const struct iio_info ad7606_info_range = { .read_raw = &ad7606_read_raw, .write_raw = &ad7606_write_raw, .attrs = &ad7606_attribute_group_range, + .validate_trigger = &ad7606_validate_trigger, +}; + +static const struct iio_trigger_ops ad7606_trigger_ops = { + .validate_device = iio_trigger_validate_own_device, }; static void ad7606_regulator_disable(void *data) @@ -434,7 +470,6 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, /* tied to logic low, analog input range is +/- 5V */ st->range = 0; st->oversampling = 1; - INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring); st->reg = devm_regulator_get(dev, "avcc"); if (IS_ERR(st->reg)) @@ -479,14 +514,32 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, if (ret) dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); - ret = devm_request_irq(dev, irq, ad7606_interrupt, IRQF_TRIGGER_FALLING, - name, indio_dev); + st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", + indio_dev->name, indio_dev->id); + if (!st->trig) + return -ENOMEM; + + st->trig->ops = &ad7606_trigger_ops; + st->trig->dev.parent = dev; + iio_trigger_set_drvdata(st->trig, indio_dev); + ret = devm_iio_trigger_register(dev, st->trig); + if (ret) + return ret; + + indio_dev->trig = iio_trigger_get(st->trig); + + ret = devm_request_threaded_irq(dev, irq, + NULL, + &ad7606_interrupt, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + name, indio_dev); if (ret) return ret; ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + &iio_pollfunc_store_time, &ad7606_trigger_handler, - NULL, NULL); + &ad7606_buffer_ops); if (ret) return ret; diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index 3e12fff2f1ad..9a832d208acf 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -26,8 +26,6 @@ struct ad7606_chip_info { * @dev pointer to kernel device * @chip_info entry in the table of chips that describes this device * @reg regulator info for the the power supply of the device - * @poll_work work struct for continuously reading data from the device - * into an IIO triggered buffer * @bops bus operations (SPI or parallel) * @range voltage range selection, selects which scale to apply * @oversampling oversampling selection @@ -42,14 +40,13 @@ struct ad7606_chip_info { * is being read on the first channel * @gpio_os GPIO descriptors to control oversampling on the device * @complete completion to indicate end of conversion + * @trig The IIO trigger associated with the device. * @data buffer for reading data from the device */ - struct ad7606_state { struct device *dev; const struct ad7606_chip_info *chip_info; struct regulator *reg; - struct work_struct poll_work; const struct ad7606_bus_ops *bops; unsigned int range; unsigned int oversampling; @@ -62,6 +59,7 @@ struct ad7606_state { struct gpio_desc *gpio_standby; struct gpio_desc *gpio_frstdata; struct gpio_descs *gpio_os; + struct iio_trigger *trig; struct completion completion; /* -- cgit From 54160ae3b2d3b45824da90a64d81c9a148c6fdbf Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Mon, 17 Dec 2018 14:23:38 +0200 Subject: staging: iio: adc: ad7606: Misc style fixes (no functional change) * Placed includes in alphabetical order * Added brackets around num and mask through out for AD760X_CHANNEL * Used single line comments where needed * Removed extra lines and spaces Signed-off-by: Stefan Popa Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606.c | 27 ++++++++++++--------------- drivers/staging/iio/adc/ad7606.h | 1 - drivers/staging/iio/adc/ad7606_par.c | 27 ++++++++------------------- drivers/staging/iio/adc/ad7606_spi.c | 16 ++++++++-------- 4 files changed, 28 insertions(+), 43 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/staging/iio/adc/ad7606.c index 50d88571e4ac..ebb8de03bbce 100644 --- a/drivers/staging/iio/adc/ad7606.c +++ b/drivers/staging/iio/adc/ad7606.c @@ -5,25 +5,25 @@ * Copyright 2011 Analog Devices Inc. */ -#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 #include "ad7606.h" @@ -249,8 +249,7 @@ static const struct attribute_group ad7606_attribute_group_range = { .attrs = ad7606_attributes_range, }; -#define AD760X_CHANNEL(num, mask) \ - { \ +#define AD760X_CHANNEL(num, mask) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = num, \ @@ -265,7 +264,7 @@ static const struct attribute_group ad7606_attribute_group_range = { .storagebits = 16, \ .endianness = IIO_CPU, \ }, \ - } +} #define AD7605_CHANNEL(num) \ AD760X_CHANNEL(num, 0) @@ -294,9 +293,7 @@ static const struct iio_chan_spec ad7606_channels[] = { }; static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { - /* - * More devices added in future - */ + /* More devices added in future */ [ID_AD7605_4] = { .channels = ad7605_channels, .num_channels = 5, diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h index 9a832d208acf..5d12410f68e1 100644 --- a/drivers/staging/iio/adc/ad7606.h +++ b/drivers/staging/iio/adc/ad7606.h @@ -14,7 +14,6 @@ * @num_channels: number of channels * @has_oversampling: whether the device has oversampling support */ - struct ad7606_chip_info { const struct iio_chan_spec *channels; unsigned int num_channels; diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c index ae0867fd4b99..1b08028facde 100644 --- a/drivers/staging/iio/adc/ad7606_par.c +++ b/drivers/staging/iio/adc/ad7606_par.c @@ -26,7 +26,7 @@ static int ad7606_par16_read_block(struct device *dev, } static const struct ad7606_bus_ops ad7606_par16_bops = { - .read_block = ad7606_par16_read_block, + .read_block = ad7606_par16_read_block, }; static int ad7606_par8_read_block(struct device *dev, @@ -41,7 +41,7 @@ static int ad7606_par8_read_block(struct device *dev, } static const struct ad7606_bus_ops ad7606_par8_bops = { - .read_block = ad7606_par8_read_block, + .read_block = ad7606_par8_read_block, }; static int ad7606_par_probe(struct platform_device *pdev) @@ -72,22 +72,12 @@ static int ad7606_par_probe(struct platform_device *pdev) } static const struct platform_device_id ad7606_driver_ids[] = { - { - .name = "ad7605-4", - .driver_data = ID_AD7605_4, - }, { - .name = "ad7606-8", - .driver_data = ID_AD7606_8, - }, { - .name = "ad7606-6", - .driver_data = ID_AD7606_6, - }, { - .name = "ad7606-4", - .driver_data = ID_AD7606_4, - }, + { .name = "ad7605-4", .driver_data = ID_AD7605_4, }, + { .name = "ad7606-4", .driver_data = ID_AD7606_4, }, + { .name = "ad7606-6", .driver_data = ID_AD7606_6, }, + { .name = "ad7606-8", .driver_data = ID_AD7606_8, }, { } }; - MODULE_DEVICE_TABLE(platform, ad7606_driver_ids); static const struct of_device_id ad7606_of_match[] = { @@ -103,12 +93,11 @@ static struct platform_driver ad7606_driver = { .probe = ad7606_par_probe, .id_table = ad7606_driver_ids, .driver = { - .name = "ad7606", - .pm = AD7606_PM_OPS, + .name = "ad7606", + .pm = AD7606_PM_OPS, .of_match_table = ad7606_of_match, }, }; - module_platform_driver(ad7606_driver); MODULE_AUTHOR("Michael Hennerich "); diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c index a69c26537a47..4fd0ec36a086 100644 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ b/drivers/staging/iio/adc/ad7606_spi.c @@ -36,7 +36,7 @@ static int ad7606_spi_read_block(struct device *dev, } static const struct ad7606_bus_ops ad7606_spi_bops = { - .read_block = ad7606_spi_read_block, + .read_block = ad7606_spi_read_block, }; static int ad7606_spi_probe(struct spi_device *spi) @@ -48,14 +48,14 @@ static int ad7606_spi_probe(struct spi_device *spi) &ad7606_spi_bops); } -static const struct spi_device_id ad7606_id[] = { - {"ad7605-4", ID_AD7605_4}, - {"ad7606-8", ID_AD7606_8}, - {"ad7606-6", ID_AD7606_6}, - {"ad7606-4", ID_AD7606_4}, +static const struct spi_device_id ad7606_id_table[] = { + { "ad7605-4", ID_AD7605_4 }, + { "ad7606-4", ID_AD7606_4 }, + { "ad7606-6", ID_AD7606_6 }, + { "ad7606-8", ID_AD7606_8 }, {} }; -MODULE_DEVICE_TABLE(spi, ad7606_id); +MODULE_DEVICE_TABLE(spi, ad7606_id_table); static const struct of_device_id ad7606_of_match[] = { { .compatible = "adi,ad7605-4" }, @@ -73,7 +73,7 @@ static struct spi_driver ad7606_driver = { .pm = AD7606_PM_OPS, }, .probe = ad7606_spi_probe, - .id_table = ad7606_id, + .id_table = ad7606_id_table, }; module_spi_driver(ad7606_driver); -- cgit From 2985a5d88455a3edd51358fc77f61b684d0e9265 Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Mon, 17 Dec 2018 14:23:39 +0200 Subject: staging: iio: adc: ad7606: Move out of staging Move ad7606 ADC driver out of staging and into the mainline. Signed-off-by: Stefan Popa Signed-off-by: Jonathan Cameron --- MAINTAINERS | 7 + drivers/iio/adc/Kconfig | 27 ++ drivers/iio/adc/Makefile | 3 + drivers/iio/adc/ad7606.c | 583 +++++++++++++++++++++++++++++++++++ drivers/iio/adc/ad7606.h | 99 ++++++ drivers/iio/adc/ad7606_par.c | 105 +++++++ drivers/iio/adc/ad7606_spi.c | 82 +++++ drivers/staging/iio/adc/Kconfig | 27 -- drivers/staging/iio/adc/Makefile | 4 - drivers/staging/iio/adc/ad7606.c | 583 ----------------------------------- drivers/staging/iio/adc/ad7606.h | 99 ------ drivers/staging/iio/adc/ad7606_par.c | 105 ------- drivers/staging/iio/adc/ad7606_spi.c | 82 ----- 13 files changed, 906 insertions(+), 900 deletions(-) create mode 100644 drivers/iio/adc/ad7606.c create mode 100644 drivers/iio/adc/ad7606.h create mode 100644 drivers/iio/adc/ad7606_par.c create mode 100644 drivers/iio/adc/ad7606_spi.c delete mode 100644 drivers/staging/iio/adc/ad7606.c delete mode 100644 drivers/staging/iio/adc/ad7606.h delete mode 100644 drivers/staging/iio/adc/ad7606_par.c delete mode 100644 drivers/staging/iio/adc/ad7606_spi.c diff --git a/MAINTAINERS b/MAINTAINERS index db9fcf23e7a2..bc9f816822d8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -854,6 +854,13 @@ S: Supported F: drivers/iio/adc/ad7124.c F: Documentation/devicetree/bindings/iio/adc/adi,ad7124.txt +ANALOG DEVICES INC AD7606 DRIVER +M: Stefan Popa +L: linux-iio@vger.kernel.org +W: http://ez.analog.com/community/linux-device-drivers +S: Supported +F: drivers/iio/adc/ad7606.c + ANALOG DEVICES INC AD9389B DRIVER M: Hans Verkuil L: linux-media@vger.kernel.org diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 7a3ca4ec0cb7..f3cc7a31bce5 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -69,6 +69,33 @@ config AD7476 To compile this driver as a module, choose M here: the module will be called ad7476. +config AD7606 + tristate + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + +config AD7606_IFACE_PARALLEL + tristate "Analog Devices AD7606 ADC driver with parallel interface support" + depends on HAS_IOMEM + select AD7606 + help + Say yes here to build parallel interface support for Analog Devices: + ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). + + To compile this driver as a module, choose M here: the + module will be called ad7606_parallel. + +config AD7606_IFACE_SPI + tristate "Analog Devices AD7606 ADC driver with spi interface support" + depends on SPI + select AD7606 + help + Say yes here to build spi interface support for Analog Devices: + ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). + + To compile this driver as a module, choose M here: the + module will be called ad7606_spi. + config AD7766 tristate "Analog Devices AD7766/AD7767 ADC driver" depends on SPI_MASTER diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 07df37f621bd..ea5031348052 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -11,6 +11,9 @@ obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7298) += ad7298.o obj-$(CONFIG_AD7923) += ad7923.o obj-$(CONFIG_AD7476) += ad7476.o +obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o +obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o +obj-$(CONFIG_AD7606) += ad7606.o obj-$(CONFIG_AD7766) += ad7766.o obj-$(CONFIG_AD7791) += ad7791.o obj-$(CONFIG_AD7793) += ad7793.o diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c new file mode 100644 index 000000000000..ebb8de03bbce --- /dev/null +++ b/drivers/iio/adc/ad7606.c @@ -0,0 +1,583 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AD7606 SPI ADC driver + * + * Copyright 2011 Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ad7606.h" + +/* + * Scales are computed as 5000/32768 and 10000/32768 respectively, + * so that when applied to the raw values they provide mV values + */ +static const unsigned int scale_avail[2] = { + 152588, 305176 +}; + +static const unsigned int ad7606_oversampling_avail[7] = { + 1, 2, 4, 8, 16, 32, 64, +}; + +static int ad7606_reset(struct ad7606_state *st) +{ + if (st->gpio_reset) { + gpiod_set_value(st->gpio_reset, 1); + ndelay(100); /* t_reset >= 100ns */ + gpiod_set_value(st->gpio_reset, 0); + return 0; + } + + return -ENODEV; +} + +static int ad7606_read_samples(struct ad7606_state *st) +{ + unsigned int num = st->chip_info->num_channels; + u16 *data = st->data; + int ret; + + /* + * The frstdata signal is set to high while and after reading the sample + * of the first channel and low for all other channels. This can be used + * to check that the incoming data is correctly aligned. During normal + * operation the data should never become unaligned, but some glitch or + * electrostatic discharge might cause an extra read or clock cycle. + * Monitoring the frstdata signal allows to recover from such failure + * situations. + */ + + if (st->gpio_frstdata) { + ret = st->bops->read_block(st->dev, 1, data); + if (ret) + return ret; + + if (!gpiod_get_value(st->gpio_frstdata)) { + ad7606_reset(st); + return -EIO; + } + + data++; + num--; + } + + return st->bops->read_block(st->dev, num, data); +} + +static irqreturn_t ad7606_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ad7606_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&st->lock); + + ret = ad7606_read_samples(st); + if (ret == 0) + iio_push_to_buffers_with_timestamp(indio_dev, st->data, + iio_get_time_ns(indio_dev)); + + iio_trigger_notify_done(indio_dev->trig); + /* The rising edge of the CONVST signal starts a new conversion. */ + gpiod_set_value(st->gpio_convst, 1); + + mutex_unlock(&st->lock); + + return IRQ_HANDLED; +} + +static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch) +{ + struct ad7606_state *st = iio_priv(indio_dev); + int ret; + + gpiod_set_value(st->gpio_convst, 1); + ret = wait_for_completion_timeout(&st->completion, + msecs_to_jiffies(1000)); + if (!ret) { + ret = -ETIMEDOUT; + goto error_ret; + } + + ret = ad7606_read_samples(st); + if (ret == 0) + ret = st->data[ch]; + +error_ret: + gpiod_set_value(st->gpio_convst, 0); + + return ret; +} + +static int ad7606_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long m) +{ + int ret; + struct ad7606_state *st = iio_priv(indio_dev); + + switch (m) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = ad7606_scan_direct(indio_dev, chan->address); + iio_device_release_direct_mode(indio_dev); + + if (ret < 0) + return ret; + *val = (short)ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = scale_avail[st->range]; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *val = st->oversampling; + return IIO_VAL_INT; + } + return -EINVAL; +} + +static ssize_t in_voltage_scale_available_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int i, len = 0; + + for (i = 0; i < ARRAY_SIZE(scale_avail); i++) + len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", + scale_avail[i]); + + buf[len - 1] = '\n'; + + return len; +} + +static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0); + +static int ad7606_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad7606_state *st = iio_priv(indio_dev); + DECLARE_BITMAP(values, 3); + int i; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + mutex_lock(&st->lock); + i = find_closest(val2, scale_avail, ARRAY_SIZE(scale_avail)); + gpiod_set_value(st->gpio_range, i); + st->range = i; + mutex_unlock(&st->lock); + + return 0; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + if (val2) + return -EINVAL; + i = find_closest(val, ad7606_oversampling_avail, + ARRAY_SIZE(ad7606_oversampling_avail)); + + values[0] = i; + + mutex_lock(&st->lock); + gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, + st->gpio_os->info, values); + st->oversampling = ad7606_oversampling_avail[i]; + mutex_unlock(&st->lock); + + return 0; + default: + return -EINVAL; + } +} + +static IIO_CONST_ATTR(oversampling_ratio_available, "1 2 4 8 16 32 64"); + +static struct attribute *ad7606_attributes_os_and_range[] = { + &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, + &iio_const_attr_oversampling_ratio_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7606_attribute_group_os_and_range = { + .attrs = ad7606_attributes_os_and_range, +}; + +static struct attribute *ad7606_attributes_os[] = { + &iio_const_attr_oversampling_ratio_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7606_attribute_group_os = { + .attrs = ad7606_attributes_os, +}; + +static struct attribute *ad7606_attributes_range[] = { + &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7606_attribute_group_range = { + .attrs = ad7606_attributes_range, +}; + +#define AD760X_CHANNEL(num, mask) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = num, \ + .address = num, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ + .info_mask_shared_by_all = mask, \ + .scan_index = num, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ +} + +#define AD7605_CHANNEL(num) \ + AD760X_CHANNEL(num, 0) + +#define AD7606_CHANNEL(num) \ + AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) + +static const struct iio_chan_spec ad7605_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(4), + AD7605_CHANNEL(0), + AD7605_CHANNEL(1), + AD7605_CHANNEL(2), + AD7605_CHANNEL(3), +}; + +static const struct iio_chan_spec ad7606_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(8), + AD7606_CHANNEL(0), + AD7606_CHANNEL(1), + AD7606_CHANNEL(2), + AD7606_CHANNEL(3), + AD7606_CHANNEL(4), + AD7606_CHANNEL(5), + AD7606_CHANNEL(6), + AD7606_CHANNEL(7), +}; + +static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { + /* More devices added in future */ + [ID_AD7605_4] = { + .channels = ad7605_channels, + .num_channels = 5, + }, + [ID_AD7606_8] = { + .channels = ad7606_channels, + .num_channels = 9, + .has_oversampling = true, + }, + [ID_AD7606_6] = { + .channels = ad7606_channels, + .num_channels = 7, + .has_oversampling = true, + }, + [ID_AD7606_4] = { + .channels = ad7606_channels, + .num_channels = 5, + .has_oversampling = true, + }, +}; + +static int ad7606_request_gpios(struct ad7606_state *st) +{ + struct device *dev = st->dev; + + st->gpio_convst = devm_gpiod_get(dev, "adi,conversion-start", + GPIOD_OUT_LOW); + if (IS_ERR(st->gpio_convst)) + return PTR_ERR(st->gpio_convst); + + st->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(st->gpio_reset)) + return PTR_ERR(st->gpio_reset); + + st->gpio_range = devm_gpiod_get_optional(dev, "adi,range", + GPIOD_OUT_LOW); + if (IS_ERR(st->gpio_range)) + return PTR_ERR(st->gpio_range); + + st->gpio_standby = devm_gpiod_get_optional(dev, "standby", + GPIOD_OUT_HIGH); + if (IS_ERR(st->gpio_standby)) + return PTR_ERR(st->gpio_standby); + + st->gpio_frstdata = devm_gpiod_get_optional(dev, "adi,first-data", + GPIOD_IN); + if (IS_ERR(st->gpio_frstdata)) + return PTR_ERR(st->gpio_frstdata); + + if (!st->chip_info->has_oversampling) + return 0; + + st->gpio_os = devm_gpiod_get_array_optional(dev, + "adi,oversampling-ratio", + GPIOD_OUT_LOW); + return PTR_ERR_OR_ZERO(st->gpio_os); +} + +/* + * The BUSY signal indicates when conversions are in progress, so when a rising + * edge of CONVST is applied, BUSY goes logic high and transitions low at the + * end of the entire conversion process. The falling edge of the BUSY signal + * triggers this interrupt. + */ +static irqreturn_t ad7606_interrupt(int irq, void *dev_id) +{ + struct iio_dev *indio_dev = dev_id; + struct ad7606_state *st = iio_priv(indio_dev); + + if (iio_buffer_enabled(indio_dev)) { + gpiod_set_value(st->gpio_convst, 0); + iio_trigger_poll_chained(st->trig); + } else { + complete(&st->completion); + } + + return IRQ_HANDLED; +}; + +static int ad7606_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + if (st->trig != trig) + return -EINVAL; + + return 0; +} + +static int ad7606_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + iio_triggered_buffer_postenable(indio_dev); + gpiod_set_value(st->gpio_convst, 1); + + return 0; +} + +static int ad7606_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + gpiod_set_value(st->gpio_convst, 0); + + return iio_triggered_buffer_predisable(indio_dev); +} + +static const struct iio_buffer_setup_ops ad7606_buffer_ops = { + .postenable = &ad7606_buffer_postenable, + .predisable = &ad7606_buffer_predisable, +}; + +static const struct iio_info ad7606_info_no_os_or_range = { + .read_raw = &ad7606_read_raw, + .validate_trigger = &ad7606_validate_trigger, +}; + +static const struct iio_info ad7606_info_os_and_range = { + .read_raw = &ad7606_read_raw, + .write_raw = &ad7606_write_raw, + .attrs = &ad7606_attribute_group_os_and_range, + .validate_trigger = &ad7606_validate_trigger, +}; + +static const struct iio_info ad7606_info_os = { + .read_raw = &ad7606_read_raw, + .write_raw = &ad7606_write_raw, + .attrs = &ad7606_attribute_group_os, + .validate_trigger = &ad7606_validate_trigger, +}; + +static const struct iio_info ad7606_info_range = { + .read_raw = &ad7606_read_raw, + .write_raw = &ad7606_write_raw, + .attrs = &ad7606_attribute_group_range, + .validate_trigger = &ad7606_validate_trigger, +}; + +static const struct iio_trigger_ops ad7606_trigger_ops = { + .validate_device = iio_trigger_validate_own_device, +}; + +static void ad7606_regulator_disable(void *data) +{ + struct ad7606_state *st = data; + + regulator_disable(st->reg); +} + +int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, + const char *name, unsigned int id, + const struct ad7606_bus_ops *bops) +{ + struct ad7606_state *st; + int ret; + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + dev_set_drvdata(dev, indio_dev); + + st->dev = dev; + mutex_init(&st->lock); + st->bops = bops; + st->base_address = base_address; + /* tied to logic low, analog input range is +/- 5V */ + st->range = 0; + st->oversampling = 1; + + st->reg = devm_regulator_get(dev, "avcc"); + if (IS_ERR(st->reg)) + return PTR_ERR(st->reg); + + ret = regulator_enable(st->reg); + if (ret) { + dev_err(dev, "Failed to enable specified AVcc supply\n"); + return ret; + } + + ret = devm_add_action_or_reset(dev, ad7606_regulator_disable, st); + if (ret) + return ret; + + st->chip_info = &ad7606_chip_info_tbl[id]; + + ret = ad7606_request_gpios(st); + if (ret) + return ret; + + indio_dev->dev.parent = dev; + if (st->gpio_os) { + if (st->gpio_range) + indio_dev->info = &ad7606_info_os_and_range; + else + indio_dev->info = &ad7606_info_os; + } else { + if (st->gpio_range) + indio_dev->info = &ad7606_info_range; + else + indio_dev->info = &ad7606_info_no_os_or_range; + } + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->name = name; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; + + init_completion(&st->completion); + + ret = ad7606_reset(st); + if (ret) + dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); + + st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", + indio_dev->name, indio_dev->id); + if (!st->trig) + return -ENOMEM; + + st->trig->ops = &ad7606_trigger_ops; + st->trig->dev.parent = dev; + iio_trigger_set_drvdata(st->trig, indio_dev); + ret = devm_iio_trigger_register(dev, st->trig); + if (ret) + return ret; + + indio_dev->trig = iio_trigger_get(st->trig); + + ret = devm_request_threaded_irq(dev, irq, + NULL, + &ad7606_interrupt, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + name, indio_dev); + if (ret) + return ret; + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + &iio_pollfunc_store_time, + &ad7606_trigger_handler, + &ad7606_buffer_ops); + if (ret) + return ret; + + return devm_iio_device_register(dev, indio_dev); +} +EXPORT_SYMBOL_GPL(ad7606_probe); + +#ifdef CONFIG_PM_SLEEP + +static int ad7606_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7606_state *st = iio_priv(indio_dev); + + if (st->gpio_standby) { + gpiod_set_value(st->gpio_range, 1); + gpiod_set_value(st->gpio_standby, 0); + } + + return 0; +} + +static int ad7606_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7606_state *st = iio_priv(indio_dev); + + if (st->gpio_standby) { + gpiod_set_value(st->gpio_range, st->range); + gpiod_set_value(st->gpio_standby, 1); + ad7606_reset(st); + } + + return 0; +} + +SIMPLE_DEV_PM_OPS(ad7606_pm_ops, ad7606_suspend, ad7606_resume); +EXPORT_SYMBOL_GPL(ad7606_pm_ops); + +#endif + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h new file mode 100644 index 000000000000..5d12410f68e1 --- /dev/null +++ b/drivers/iio/adc/ad7606.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * AD7606 ADC driver + * + * Copyright 2011 Analog Devices Inc. + */ + +#ifndef IIO_ADC_AD7606_H_ +#define IIO_ADC_AD7606_H_ + +/** + * struct ad7606_chip_info - chip specific information + * @channels: channel specification + * @num_channels: number of channels + * @has_oversampling: whether the device has oversampling support + */ +struct ad7606_chip_info { + const struct iio_chan_spec *channels; + unsigned int num_channels; + bool has_oversampling; +}; + +/** + * struct ad7606_state - driver instance specific data + * @dev pointer to kernel device + * @chip_info entry in the table of chips that describes this device + * @reg regulator info for the the power supply of the device + * @bops bus operations (SPI or parallel) + * @range voltage range selection, selects which scale to apply + * @oversampling oversampling selection + * @base_address address from where to read data in parallel operation + * @lock protect sensor state from concurrent accesses to GPIOs + * @gpio_convst GPIO descriptor for conversion start signal (CONVST) + * @gpio_reset GPIO descriptor for device hard-reset + * @gpio_range GPIO descriptor for range selection + * @gpio_standby GPIO descriptor for stand-by signal (STBY), + * controls power-down mode of device + * @gpio_frstdata GPIO descriptor for reading from device when data + * is being read on the first channel + * @gpio_os GPIO descriptors to control oversampling on the device + * @complete completion to indicate end of conversion + * @trig The IIO trigger associated with the device. + * @data buffer for reading data from the device + */ +struct ad7606_state { + struct device *dev; + const struct ad7606_chip_info *chip_info; + struct regulator *reg; + const struct ad7606_bus_ops *bops; + unsigned int range; + unsigned int oversampling; + void __iomem *base_address; + + struct mutex lock; /* protect sensor state */ + struct gpio_desc *gpio_convst; + struct gpio_desc *gpio_reset; + struct gpio_desc *gpio_range; + struct gpio_desc *gpio_standby; + struct gpio_desc *gpio_frstdata; + struct gpio_descs *gpio_os; + struct iio_trigger *trig; + struct completion completion; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + * 8 * 16-bit samples + 64-bit timestamp + */ + unsigned short data[12] ____cacheline_aligned; +}; + +/** + * struct ad7606_bus_ops - driver bus operations + * @read_block function pointer for reading blocks of data + */ +struct ad7606_bus_ops { + /* more methods added in future? */ + int (*read_block)(struct device *dev, int num, void *data); +}; + +int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, + const char *name, unsigned int id, + const struct ad7606_bus_ops *bops); + +enum ad7606_supported_device_ids { + ID_AD7605_4, + ID_AD7606_8, + ID_AD7606_6, + ID_AD7606_4 +}; + +#ifdef CONFIG_PM_SLEEP +extern const struct dev_pm_ops ad7606_pm_ops; +#define AD7606_PM_OPS (&ad7606_pm_ops) +#else +#define AD7606_PM_OPS NULL +#endif + +#endif /* IIO_ADC_AD7606_H_ */ diff --git a/drivers/iio/adc/ad7606_par.c b/drivers/iio/adc/ad7606_par.c new file mode 100644 index 000000000000..1b08028facde --- /dev/null +++ b/drivers/iio/adc/ad7606_par.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AD7606 Parallel Interface ADC driver + * + * Copyright 2011 Analog Devices Inc. + */ + +#include +#include +#include +#include +#include + +#include +#include "ad7606.h" + +static int ad7606_par16_read_block(struct device *dev, + int count, void *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7606_state *st = iio_priv(indio_dev); + + insw((unsigned long)st->base_address, buf, count); + + return 0; +} + +static const struct ad7606_bus_ops ad7606_par16_bops = { + .read_block = ad7606_par16_read_block, +}; + +static int ad7606_par8_read_block(struct device *dev, + int count, void *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct ad7606_state *st = iio_priv(indio_dev); + + insb((unsigned long)st->base_address, buf, count * 2); + + return 0; +} + +static const struct ad7606_bus_ops ad7606_par8_bops = { + .read_block = ad7606_par8_read_block, +}; + +static int ad7606_par_probe(struct platform_device *pdev) +{ + const struct platform_device_id *id = platform_get_device_id(pdev); + struct resource *res; + void __iomem *addr; + resource_size_t remap_size; + int irq; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no irq: %d\n", irq); + return irq; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(addr)) + return PTR_ERR(addr); + + remap_size = resource_size(res); + + return ad7606_probe(&pdev->dev, irq, addr, + id->name, id->driver_data, + remap_size > 1 ? &ad7606_par16_bops : + &ad7606_par8_bops); +} + +static const struct platform_device_id ad7606_driver_ids[] = { + { .name = "ad7605-4", .driver_data = ID_AD7605_4, }, + { .name = "ad7606-4", .driver_data = ID_AD7606_4, }, + { .name = "ad7606-6", .driver_data = ID_AD7606_6, }, + { .name = "ad7606-8", .driver_data = ID_AD7606_8, }, + { } +}; +MODULE_DEVICE_TABLE(platform, ad7606_driver_ids); + +static const struct of_device_id ad7606_of_match[] = { + { .compatible = "adi,ad7605-4" }, + { .compatible = "adi,ad7606-4" }, + { .compatible = "adi,ad7606-6" }, + { .compatible = "adi,ad7606-8" }, + { }, +}; +MODULE_DEVICE_TABLE(of, ad7606_of_match); + +static struct platform_driver ad7606_driver = { + .probe = ad7606_par_probe, + .id_table = ad7606_driver_ids, + .driver = { + .name = "ad7606", + .pm = AD7606_PM_OPS, + .of_match_table = ad7606_of_match, + }, +}; +module_platform_driver(ad7606_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c new file mode 100644 index 000000000000..4fd0ec36a086 --- /dev/null +++ b/drivers/iio/adc/ad7606_spi.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AD7606 SPI ADC driver + * + * Copyright 2011 Analog Devices Inc. + */ + +#include +#include +#include +#include + +#include +#include "ad7606.h" + +#define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */ + +static int ad7606_spi_read_block(struct device *dev, + int count, void *buf) +{ + struct spi_device *spi = to_spi_device(dev); + int i, ret; + unsigned short *data = buf; + __be16 *bdata = buf; + + ret = spi_read(spi, buf, count * 2); + if (ret < 0) { + dev_err(&spi->dev, "SPI read error\n"); + return ret; + } + + for (i = 0; i < count; i++) + data[i] = be16_to_cpu(bdata[i]); + + return 0; +} + +static const struct ad7606_bus_ops ad7606_spi_bops = { + .read_block = ad7606_spi_read_block, +}; + +static int ad7606_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + + return ad7606_probe(&spi->dev, spi->irq, NULL, + id->name, id->driver_data, + &ad7606_spi_bops); +} + +static const struct spi_device_id ad7606_id_table[] = { + { "ad7605-4", ID_AD7605_4 }, + { "ad7606-4", ID_AD7606_4 }, + { "ad7606-6", ID_AD7606_6 }, + { "ad7606-8", ID_AD7606_8 }, + {} +}; +MODULE_DEVICE_TABLE(spi, ad7606_id_table); + +static const struct of_device_id ad7606_of_match[] = { + { .compatible = "adi,ad7605-4" }, + { .compatible = "adi,ad7606-4" }, + { .compatible = "adi,ad7606-6" }, + { .compatible = "adi,ad7606-8" }, + { }, +}; +MODULE_DEVICE_TABLE(of, ad7606_of_match); + +static struct spi_driver ad7606_driver = { + .driver = { + .name = "ad7606", + .of_match_table = ad7606_of_match, + .pm = AD7606_PM_OPS, + }, + .probe = ad7606_spi_probe, + .id_table = ad7606_id_table, +}; +module_spi_driver(ad7606_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index 302639ab9c89..7a93d3a5c113 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -3,33 +3,6 @@ # menu "Analog to digital converters" -config AD7606 - tristate - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - -config AD7606_IFACE_PARALLEL - tristate "Analog Devices AD7606 ADC driver with parallel interface support" - depends on HAS_IOMEM - select AD7606 - help - Say yes here to build parallel interface support for Analog Devices: - ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). - - To compile this driver as a module, choose M here: the - module will be called ad7606_parallel. - -config AD7606_IFACE_SPI - tristate "Analog Devices AD7606 ADC driver with spi interface support" - depends on SPI - select AD7606 - help - Say yes here to build spi interface support for Analog Devices: - ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). - - To compile this driver as a module, choose M here: the - module will be called ad7606_spi. - config AD7780 tristate "Analog Devices AD7780 and similar ADCs driver" depends on SPI diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index ebe83c1ad362..7a421088ff82 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -3,10 +3,6 @@ # Makefile for industrial I/O ADC drivers # -obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o -obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o -obj-$(CONFIG_AD7606) += ad7606.o - obj-$(CONFIG_AD7780) += ad7780.o obj-$(CONFIG_AD7816) += ad7816.o obj-$(CONFIG_AD7192) += ad7192.o diff --git a/drivers/staging/iio/adc/ad7606.c b/drivers/staging/iio/adc/ad7606.c deleted file mode 100644 index ebb8de03bbce..000000000000 --- a/drivers/staging/iio/adc/ad7606.c +++ /dev/null @@ -1,583 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * AD7606 SPI ADC driver - * - * Copyright 2011 Analog Devices Inc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "ad7606.h" - -/* - * Scales are computed as 5000/32768 and 10000/32768 respectively, - * so that when applied to the raw values they provide mV values - */ -static const unsigned int scale_avail[2] = { - 152588, 305176 -}; - -static const unsigned int ad7606_oversampling_avail[7] = { - 1, 2, 4, 8, 16, 32, 64, -}; - -static int ad7606_reset(struct ad7606_state *st) -{ - if (st->gpio_reset) { - gpiod_set_value(st->gpio_reset, 1); - ndelay(100); /* t_reset >= 100ns */ - gpiod_set_value(st->gpio_reset, 0); - return 0; - } - - return -ENODEV; -} - -static int ad7606_read_samples(struct ad7606_state *st) -{ - unsigned int num = st->chip_info->num_channels; - u16 *data = st->data; - int ret; - - /* - * The frstdata signal is set to high while and after reading the sample - * of the first channel and low for all other channels. This can be used - * to check that the incoming data is correctly aligned. During normal - * operation the data should never become unaligned, but some glitch or - * electrostatic discharge might cause an extra read or clock cycle. - * Monitoring the frstdata signal allows to recover from such failure - * situations. - */ - - if (st->gpio_frstdata) { - ret = st->bops->read_block(st->dev, 1, data); - if (ret) - return ret; - - if (!gpiod_get_value(st->gpio_frstdata)) { - ad7606_reset(st); - return -EIO; - } - - data++; - num--; - } - - return st->bops->read_block(st->dev, num, data); -} - -static irqreturn_t ad7606_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct ad7606_state *st = iio_priv(indio_dev); - int ret; - - mutex_lock(&st->lock); - - ret = ad7606_read_samples(st); - if (ret == 0) - iio_push_to_buffers_with_timestamp(indio_dev, st->data, - iio_get_time_ns(indio_dev)); - - iio_trigger_notify_done(indio_dev->trig); - /* The rising edge of the CONVST signal starts a new conversion. */ - gpiod_set_value(st->gpio_convst, 1); - - mutex_unlock(&st->lock); - - return IRQ_HANDLED; -} - -static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch) -{ - struct ad7606_state *st = iio_priv(indio_dev); - int ret; - - gpiod_set_value(st->gpio_convst, 1); - ret = wait_for_completion_timeout(&st->completion, - msecs_to_jiffies(1000)); - if (!ret) { - ret = -ETIMEDOUT; - goto error_ret; - } - - ret = ad7606_read_samples(st); - if (ret == 0) - ret = st->data[ch]; - -error_ret: - gpiod_set_value(st->gpio_convst, 0); - - return ret; -} - -static int ad7606_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, - int *val2, - long m) -{ - int ret; - struct ad7606_state *st = iio_priv(indio_dev); - - switch (m) { - case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - - ret = ad7606_scan_direct(indio_dev, chan->address); - iio_device_release_direct_mode(indio_dev); - - if (ret < 0) - return ret; - *val = (short)ret; - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = scale_avail[st->range]; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - *val = st->oversampling; - return IIO_VAL_INT; - } - return -EINVAL; -} - -static ssize_t in_voltage_scale_available_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int i, len = 0; - - for (i = 0; i < ARRAY_SIZE(scale_avail); i++) - len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", - scale_avail[i]); - - buf[len - 1] = '\n'; - - return len; -} - -static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0); - -static int ad7606_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct ad7606_state *st = iio_priv(indio_dev); - DECLARE_BITMAP(values, 3); - int i; - - switch (mask) { - case IIO_CHAN_INFO_SCALE: - mutex_lock(&st->lock); - i = find_closest(val2, scale_avail, ARRAY_SIZE(scale_avail)); - gpiod_set_value(st->gpio_range, i); - st->range = i; - mutex_unlock(&st->lock); - - return 0; - case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - if (val2) - return -EINVAL; - i = find_closest(val, ad7606_oversampling_avail, - ARRAY_SIZE(ad7606_oversampling_avail)); - - values[0] = i; - - mutex_lock(&st->lock); - gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, - st->gpio_os->info, values); - st->oversampling = ad7606_oversampling_avail[i]; - mutex_unlock(&st->lock); - - return 0; - default: - return -EINVAL; - } -} - -static IIO_CONST_ATTR(oversampling_ratio_available, "1 2 4 8 16 32 64"); - -static struct attribute *ad7606_attributes_os_and_range[] = { - &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, - &iio_const_attr_oversampling_ratio_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad7606_attribute_group_os_and_range = { - .attrs = ad7606_attributes_os_and_range, -}; - -static struct attribute *ad7606_attributes_os[] = { - &iio_const_attr_oversampling_ratio_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad7606_attribute_group_os = { - .attrs = ad7606_attributes_os, -}; - -static struct attribute *ad7606_attributes_range[] = { - &iio_dev_attr_in_voltage_scale_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad7606_attribute_group_range = { - .attrs = ad7606_attributes_range, -}; - -#define AD760X_CHANNEL(num, mask) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = num, \ - .address = num, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ - .info_mask_shared_by_all = mask, \ - .scan_index = num, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 16, \ - .storagebits = 16, \ - .endianness = IIO_CPU, \ - }, \ -} - -#define AD7605_CHANNEL(num) \ - AD760X_CHANNEL(num, 0) - -#define AD7606_CHANNEL(num) \ - AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO)) - -static const struct iio_chan_spec ad7605_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(4), - AD7605_CHANNEL(0), - AD7605_CHANNEL(1), - AD7605_CHANNEL(2), - AD7605_CHANNEL(3), -}; - -static const struct iio_chan_spec ad7606_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(8), - AD7606_CHANNEL(0), - AD7606_CHANNEL(1), - AD7606_CHANNEL(2), - AD7606_CHANNEL(3), - AD7606_CHANNEL(4), - AD7606_CHANNEL(5), - AD7606_CHANNEL(6), - AD7606_CHANNEL(7), -}; - -static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { - /* More devices added in future */ - [ID_AD7605_4] = { - .channels = ad7605_channels, - .num_channels = 5, - }, - [ID_AD7606_8] = { - .channels = ad7606_channels, - .num_channels = 9, - .has_oversampling = true, - }, - [ID_AD7606_6] = { - .channels = ad7606_channels, - .num_channels = 7, - .has_oversampling = true, - }, - [ID_AD7606_4] = { - .channels = ad7606_channels, - .num_channels = 5, - .has_oversampling = true, - }, -}; - -static int ad7606_request_gpios(struct ad7606_state *st) -{ - struct device *dev = st->dev; - - st->gpio_convst = devm_gpiod_get(dev, "adi,conversion-start", - GPIOD_OUT_LOW); - if (IS_ERR(st->gpio_convst)) - return PTR_ERR(st->gpio_convst); - - st->gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(st->gpio_reset)) - return PTR_ERR(st->gpio_reset); - - st->gpio_range = devm_gpiod_get_optional(dev, "adi,range", - GPIOD_OUT_LOW); - if (IS_ERR(st->gpio_range)) - return PTR_ERR(st->gpio_range); - - st->gpio_standby = devm_gpiod_get_optional(dev, "standby", - GPIOD_OUT_HIGH); - if (IS_ERR(st->gpio_standby)) - return PTR_ERR(st->gpio_standby); - - st->gpio_frstdata = devm_gpiod_get_optional(dev, "adi,first-data", - GPIOD_IN); - if (IS_ERR(st->gpio_frstdata)) - return PTR_ERR(st->gpio_frstdata); - - if (!st->chip_info->has_oversampling) - return 0; - - st->gpio_os = devm_gpiod_get_array_optional(dev, - "adi,oversampling-ratio", - GPIOD_OUT_LOW); - return PTR_ERR_OR_ZERO(st->gpio_os); -} - -/* - * The BUSY signal indicates when conversions are in progress, so when a rising - * edge of CONVST is applied, BUSY goes logic high and transitions low at the - * end of the entire conversion process. The falling edge of the BUSY signal - * triggers this interrupt. - */ -static irqreturn_t ad7606_interrupt(int irq, void *dev_id) -{ - struct iio_dev *indio_dev = dev_id; - struct ad7606_state *st = iio_priv(indio_dev); - - if (iio_buffer_enabled(indio_dev)) { - gpiod_set_value(st->gpio_convst, 0); - iio_trigger_poll_chained(st->trig); - } else { - complete(&st->completion); - } - - return IRQ_HANDLED; -}; - -static int ad7606_validate_trigger(struct iio_dev *indio_dev, - struct iio_trigger *trig) -{ - struct ad7606_state *st = iio_priv(indio_dev); - - if (st->trig != trig) - return -EINVAL; - - return 0; -} - -static int ad7606_buffer_postenable(struct iio_dev *indio_dev) -{ - struct ad7606_state *st = iio_priv(indio_dev); - - iio_triggered_buffer_postenable(indio_dev); - gpiod_set_value(st->gpio_convst, 1); - - return 0; -} - -static int ad7606_buffer_predisable(struct iio_dev *indio_dev) -{ - struct ad7606_state *st = iio_priv(indio_dev); - - gpiod_set_value(st->gpio_convst, 0); - - return iio_triggered_buffer_predisable(indio_dev); -} - -static const struct iio_buffer_setup_ops ad7606_buffer_ops = { - .postenable = &ad7606_buffer_postenable, - .predisable = &ad7606_buffer_predisable, -}; - -static const struct iio_info ad7606_info_no_os_or_range = { - .read_raw = &ad7606_read_raw, - .validate_trigger = &ad7606_validate_trigger, -}; - -static const struct iio_info ad7606_info_os_and_range = { - .read_raw = &ad7606_read_raw, - .write_raw = &ad7606_write_raw, - .attrs = &ad7606_attribute_group_os_and_range, - .validate_trigger = &ad7606_validate_trigger, -}; - -static const struct iio_info ad7606_info_os = { - .read_raw = &ad7606_read_raw, - .write_raw = &ad7606_write_raw, - .attrs = &ad7606_attribute_group_os, - .validate_trigger = &ad7606_validate_trigger, -}; - -static const struct iio_info ad7606_info_range = { - .read_raw = &ad7606_read_raw, - .write_raw = &ad7606_write_raw, - .attrs = &ad7606_attribute_group_range, - .validate_trigger = &ad7606_validate_trigger, -}; - -static const struct iio_trigger_ops ad7606_trigger_ops = { - .validate_device = iio_trigger_validate_own_device, -}; - -static void ad7606_regulator_disable(void *data) -{ - struct ad7606_state *st = data; - - regulator_disable(st->reg); -} - -int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, - const char *name, unsigned int id, - const struct ad7606_bus_ops *bops) -{ - struct ad7606_state *st; - int ret; - struct iio_dev *indio_dev; - - indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); - if (!indio_dev) - return -ENOMEM; - - st = iio_priv(indio_dev); - dev_set_drvdata(dev, indio_dev); - - st->dev = dev; - mutex_init(&st->lock); - st->bops = bops; - st->base_address = base_address; - /* tied to logic low, analog input range is +/- 5V */ - st->range = 0; - st->oversampling = 1; - - st->reg = devm_regulator_get(dev, "avcc"); - if (IS_ERR(st->reg)) - return PTR_ERR(st->reg); - - ret = regulator_enable(st->reg); - if (ret) { - dev_err(dev, "Failed to enable specified AVcc supply\n"); - return ret; - } - - ret = devm_add_action_or_reset(dev, ad7606_regulator_disable, st); - if (ret) - return ret; - - st->chip_info = &ad7606_chip_info_tbl[id]; - - ret = ad7606_request_gpios(st); - if (ret) - return ret; - - indio_dev->dev.parent = dev; - if (st->gpio_os) { - if (st->gpio_range) - indio_dev->info = &ad7606_info_os_and_range; - else - indio_dev->info = &ad7606_info_os; - } else { - if (st->gpio_range) - indio_dev->info = &ad7606_info_range; - else - indio_dev->info = &ad7606_info_no_os_or_range; - } - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->name = name; - indio_dev->channels = st->chip_info->channels; - indio_dev->num_channels = st->chip_info->num_channels; - - init_completion(&st->completion); - - ret = ad7606_reset(st); - if (ret) - dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); - - st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", - indio_dev->name, indio_dev->id); - if (!st->trig) - return -ENOMEM; - - st->trig->ops = &ad7606_trigger_ops; - st->trig->dev.parent = dev; - iio_trigger_set_drvdata(st->trig, indio_dev); - ret = devm_iio_trigger_register(dev, st->trig); - if (ret) - return ret; - - indio_dev->trig = iio_trigger_get(st->trig); - - ret = devm_request_threaded_irq(dev, irq, - NULL, - &ad7606_interrupt, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - name, indio_dev); - if (ret) - return ret; - - ret = devm_iio_triggered_buffer_setup(dev, indio_dev, - &iio_pollfunc_store_time, - &ad7606_trigger_handler, - &ad7606_buffer_ops); - if (ret) - return ret; - - return devm_iio_device_register(dev, indio_dev); -} -EXPORT_SYMBOL_GPL(ad7606_probe); - -#ifdef CONFIG_PM_SLEEP - -static int ad7606_suspend(struct device *dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7606_state *st = iio_priv(indio_dev); - - if (st->gpio_standby) { - gpiod_set_value(st->gpio_range, 1); - gpiod_set_value(st->gpio_standby, 0); - } - - return 0; -} - -static int ad7606_resume(struct device *dev) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7606_state *st = iio_priv(indio_dev); - - if (st->gpio_standby) { - gpiod_set_value(st->gpio_range, st->range); - gpiod_set_value(st->gpio_standby, 1); - ad7606_reset(st); - } - - return 0; -} - -SIMPLE_DEV_PM_OPS(ad7606_pm_ops, ad7606_suspend, ad7606_resume); -EXPORT_SYMBOL_GPL(ad7606_pm_ops); - -#endif - -MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h deleted file mode 100644 index 5d12410f68e1..000000000000 --- a/drivers/staging/iio/adc/ad7606.h +++ /dev/null @@ -1,99 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * AD7606 ADC driver - * - * Copyright 2011 Analog Devices Inc. - */ - -#ifndef IIO_ADC_AD7606_H_ -#define IIO_ADC_AD7606_H_ - -/** - * struct ad7606_chip_info - chip specific information - * @channels: channel specification - * @num_channels: number of channels - * @has_oversampling: whether the device has oversampling support - */ -struct ad7606_chip_info { - const struct iio_chan_spec *channels; - unsigned int num_channels; - bool has_oversampling; -}; - -/** - * struct ad7606_state - driver instance specific data - * @dev pointer to kernel device - * @chip_info entry in the table of chips that describes this device - * @reg regulator info for the the power supply of the device - * @bops bus operations (SPI or parallel) - * @range voltage range selection, selects which scale to apply - * @oversampling oversampling selection - * @base_address address from where to read data in parallel operation - * @lock protect sensor state from concurrent accesses to GPIOs - * @gpio_convst GPIO descriptor for conversion start signal (CONVST) - * @gpio_reset GPIO descriptor for device hard-reset - * @gpio_range GPIO descriptor for range selection - * @gpio_standby GPIO descriptor for stand-by signal (STBY), - * controls power-down mode of device - * @gpio_frstdata GPIO descriptor for reading from device when data - * is being read on the first channel - * @gpio_os GPIO descriptors to control oversampling on the device - * @complete completion to indicate end of conversion - * @trig The IIO trigger associated with the device. - * @data buffer for reading data from the device - */ -struct ad7606_state { - struct device *dev; - const struct ad7606_chip_info *chip_info; - struct regulator *reg; - const struct ad7606_bus_ops *bops; - unsigned int range; - unsigned int oversampling; - void __iomem *base_address; - - struct mutex lock; /* protect sensor state */ - struct gpio_desc *gpio_convst; - struct gpio_desc *gpio_reset; - struct gpio_desc *gpio_range; - struct gpio_desc *gpio_standby; - struct gpio_desc *gpio_frstdata; - struct gpio_descs *gpio_os; - struct iio_trigger *trig; - struct completion completion; - - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - * 8 * 16-bit samples + 64-bit timestamp - */ - unsigned short data[12] ____cacheline_aligned; -}; - -/** - * struct ad7606_bus_ops - driver bus operations - * @read_block function pointer for reading blocks of data - */ -struct ad7606_bus_ops { - /* more methods added in future? */ - int (*read_block)(struct device *dev, int num, void *data); -}; - -int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, - const char *name, unsigned int id, - const struct ad7606_bus_ops *bops); - -enum ad7606_supported_device_ids { - ID_AD7605_4, - ID_AD7606_8, - ID_AD7606_6, - ID_AD7606_4 -}; - -#ifdef CONFIG_PM_SLEEP -extern const struct dev_pm_ops ad7606_pm_ops; -#define AD7606_PM_OPS (&ad7606_pm_ops) -#else -#define AD7606_PM_OPS NULL -#endif - -#endif /* IIO_ADC_AD7606_H_ */ diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c deleted file mode 100644 index 1b08028facde..000000000000 --- a/drivers/staging/iio/adc/ad7606_par.c +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * AD7606 Parallel Interface ADC driver - * - * Copyright 2011 Analog Devices Inc. - */ - -#include -#include -#include -#include -#include - -#include -#include "ad7606.h" - -static int ad7606_par16_read_block(struct device *dev, - int count, void *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7606_state *st = iio_priv(indio_dev); - - insw((unsigned long)st->base_address, buf, count); - - return 0; -} - -static const struct ad7606_bus_ops ad7606_par16_bops = { - .read_block = ad7606_par16_read_block, -}; - -static int ad7606_par8_read_block(struct device *dev, - int count, void *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct ad7606_state *st = iio_priv(indio_dev); - - insb((unsigned long)st->base_address, buf, count * 2); - - return 0; -} - -static const struct ad7606_bus_ops ad7606_par8_bops = { - .read_block = ad7606_par8_read_block, -}; - -static int ad7606_par_probe(struct platform_device *pdev) -{ - const struct platform_device_id *id = platform_get_device_id(pdev); - struct resource *res; - void __iomem *addr; - resource_size_t remap_size; - int irq; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq: %d\n", irq); - return irq; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - addr = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(addr)) - return PTR_ERR(addr); - - remap_size = resource_size(res); - - return ad7606_probe(&pdev->dev, irq, addr, - id->name, id->driver_data, - remap_size > 1 ? &ad7606_par16_bops : - &ad7606_par8_bops); -} - -static const struct platform_device_id ad7606_driver_ids[] = { - { .name = "ad7605-4", .driver_data = ID_AD7605_4, }, - { .name = "ad7606-4", .driver_data = ID_AD7606_4, }, - { .name = "ad7606-6", .driver_data = ID_AD7606_6, }, - { .name = "ad7606-8", .driver_data = ID_AD7606_8, }, - { } -}; -MODULE_DEVICE_TABLE(platform, ad7606_driver_ids); - -static const struct of_device_id ad7606_of_match[] = { - { .compatible = "adi,ad7605-4" }, - { .compatible = "adi,ad7606-4" }, - { .compatible = "adi,ad7606-6" }, - { .compatible = "adi,ad7606-8" }, - { }, -}; -MODULE_DEVICE_TABLE(of, ad7606_of_match); - -static struct platform_driver ad7606_driver = { - .probe = ad7606_par_probe, - .id_table = ad7606_driver_ids, - .driver = { - .name = "ad7606", - .pm = AD7606_PM_OPS, - .of_match_table = ad7606_of_match, - }, -}; -module_platform_driver(ad7606_driver); - -MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c deleted file mode 100644 index 4fd0ec36a086..000000000000 --- a/drivers/staging/iio/adc/ad7606_spi.c +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * AD7606 SPI ADC driver - * - * Copyright 2011 Analog Devices Inc. - */ - -#include -#include -#include -#include - -#include -#include "ad7606.h" - -#define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */ - -static int ad7606_spi_read_block(struct device *dev, - int count, void *buf) -{ - struct spi_device *spi = to_spi_device(dev); - int i, ret; - unsigned short *data = buf; - __be16 *bdata = buf; - - ret = spi_read(spi, buf, count * 2); - if (ret < 0) { - dev_err(&spi->dev, "SPI read error\n"); - return ret; - } - - for (i = 0; i < count; i++) - data[i] = be16_to_cpu(bdata[i]); - - return 0; -} - -static const struct ad7606_bus_ops ad7606_spi_bops = { - .read_block = ad7606_spi_read_block, -}; - -static int ad7606_spi_probe(struct spi_device *spi) -{ - const struct spi_device_id *id = spi_get_device_id(spi); - - return ad7606_probe(&spi->dev, spi->irq, NULL, - id->name, id->driver_data, - &ad7606_spi_bops); -} - -static const struct spi_device_id ad7606_id_table[] = { - { "ad7605-4", ID_AD7605_4 }, - { "ad7606-4", ID_AD7606_4 }, - { "ad7606-6", ID_AD7606_6 }, - { "ad7606-8", ID_AD7606_8 }, - {} -}; -MODULE_DEVICE_TABLE(spi, ad7606_id_table); - -static const struct of_device_id ad7606_of_match[] = { - { .compatible = "adi,ad7605-4" }, - { .compatible = "adi,ad7606-4" }, - { .compatible = "adi,ad7606-6" }, - { .compatible = "adi,ad7606-8" }, - { }, -}; -MODULE_DEVICE_TABLE(of, ad7606_of_match); - -static struct spi_driver ad7606_driver = { - .driver = { - .name = "ad7606", - .of_match_table = ad7606_of_match, - .pm = AD7606_PM_OPS, - }, - .probe = ad7606_spi_probe, - .id_table = ad7606_id_table, -}; -module_spi_driver(ad7606_driver); - -MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); -MODULE_LICENSE("GPL v2"); -- cgit From 6e33a125df66664a09cd518a2e1dd63b4ccddef8 Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Mon, 17 Dec 2018 14:23:40 +0200 Subject: dt-bindings: iio: adc: Add docs for AD7606 ADC Document support for AD7606 Analog to Digital Converter. Signed-off-by: Stefan Popa Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/adc/adi,ad7606.txt | 65 ++++++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 66 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt new file mode 100644 index 000000000000..d7b6241ca881 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt @@ -0,0 +1,65 @@ +Analog Devices AD7606 Simultaneous Sampling ADC + +Required properties for the AD7606: + +- compatible: Must be one of + * "adi,ad7605-4" + * "adi,ad7606-8" + * "adi,ad7606-6" + * "adi,ad7606-4" +- reg: SPI chip select number for the device +- spi-max-frequency: Max SPI frequency to use + see: Documentation/devicetree/bindings/spi/spi-bus.txt +- spi-cpha: See Documentation/devicetree/bindings/spi/spi-bus.txt +- avcc-supply: phandle to the Avcc power supply +- interrupts: IRQ line for the ADC + see: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +- adi,conversion-start-gpios: must be the device tree identifier of the CONVST pin. + This logic input is used to initiate conversions on the analog + input channels. As the line is active high, it should be marked + GPIO_ACTIVE_HIGH. + +Optional properties: + +- reset-gpios: must be the device tree identifier of the RESET pin. If specified, + it will be asserted during driver probe. As the line is active high, + it should be marked GPIO_ACTIVE_HIGH. +- standby-gpios: must be the device tree identifier of the STBY pin. This pin is used + to place the AD7606 into one of two power-down modes, Standby mode or + Shutdown mode. As the line is active low, it should be marked + GPIO_ACTIVE_LOW. +- adi,first-data-gpios: must be the device tree identifier of the FRSTDATA pin. + The FRSTDATA output indicates when the first channel, V1, is + being read back on either the parallel, byte or serial interface. + As the line is active high, it should be marked GPIO_ACTIVE_HIGH. +- adi,range-gpios: must be the device tree identifier of the RANGE pin. The polarity on + this pin determines the input range of the analog input channels. If + this pin is tied to a logic high, the analog input range is ±10V for + all channels. If this pin is tied to a logic low, the analog input range + is ±5V for all channels. As the line is active high, it should be marked + GPIO_ACTIVE_HIGH. +- adi,oversampling-ratio-gpios: must be the device tree identifier of the over-sampling + mode pins. As the line is active high, it should be marked + GPIO_ACTIVE_HIGH. + +Example: + + adc@0 { + compatible = "adi,ad7606-8"; + reg = <0>; + spi-max-frequency = <1000000>; + spi-cpol; + + avcc-supply = <&adc_vref>; + + interrupts = <25 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpio>; + + adi,conversion-start-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>; + adi,first-data-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; + adi,oversampling-ratio-gpios = <&gpio 18 GPIO_ACTIVE_HIGH + &gpio 23 GPIO_ACTIVE_HIGH + &gpio 26 GPIO_ACTIVE_HIGH>; + standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index bc9f816822d8..d039f66a5cef 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -860,6 +860,7 @@ L: linux-iio@vger.kernel.org W: http://ez.analog.com/community/linux-device-drivers S: Supported F: drivers/iio/adc/ad7606.c +F: Documentation/devicetree/bindings/iio/adc/ad7606.txt ANALOG DEVICES INC AD9389B DRIVER M: Hans Verkuil -- cgit From a4b475b1abbb41b71d62e088a1ffd2b86e5e0aa0 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Thu, 27 Dec 2018 22:50:19 +0100 Subject: dt-bindings: iio: adc: meson-saradc: update temperature sensor support Meson8b and Meson8m2 use a 5-bit wide TSC (temperature sensor coefficient). The SAR ADC registers however can only store (the lower) 4 bits. The fifth (upper-most) bit is stored inside the MESON_HHI_DPLL_TOP_0[9] register from the HHI register area. This adds a syscon property to the HHI register area so a driver can fetch the HHI register map and store the fifth TSC bit in there. Signed-off-by: Martin Blumenstingl Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt index 325090e43ce6..75c775954102 100644 --- a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt +++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt @@ -23,6 +23,10 @@ Required properties: - #io-channel-cells: must be 1, see ../iio-bindings.txt Optional properties: +- amlogic,hhi-sysctrl: phandle to the syscon which contains the 5th bit + of the TSC (temperature sensor coefficient) on + Meson8b and Meson8m2 (which used to calibrate the + temperature sensor) - nvmem-cells: phandle to the temperature_calib eFuse cells - nvmem-cell-names: if present (to enable the temperature sensor calibration) this must contain "temperature_calib" -- cgit From b002bf5f8dbca8465b1dadb283154e844c61d73f Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Thu, 27 Dec 2018 22:50:20 +0100 Subject: iio: adc: meson-saradc: enable the temperature sensor two more SoCs Meson8b and Meson8m2 use the same logic to convert the ADC register value to celsius, which is different from Meson8: - Meson8 has different multiplier and divider values - Meson8 uses a 4-bit TSC (temperature sensor coefficient) which fits into the 4-bit field in the MESON_SAR_ADC_DELTA_10 register: MESON_SAR_ADC_DELTA_10_TS_C_MASK. Meson8b and Meson8m2 have a 5-bit TSC which requires writing the upper-most bit into the MESON_HHI_DPLL_TOP_0[9] register from the HHI register area. This adds support for the temperature sensor on the Meson8b and Meson8m2 SoCs by implementing the logic to write the upper-most TSC bit into the HHI register area. The SoC-specific values (temperature_trimming_bits, temperature_multiplier, temperature_divider) are added - these simply integrate into the existing infrastructure (which was implemented for Meson8) and thus require no further changes to the existing temperature calculation logic. Signed-off-by: Martin Blumenstingl Signed-off-by: Jonathan Cameron --- drivers/iio/adc/meson_saradc.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 729becb2d3d9..f8600fbcdfe3 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -26,6 +26,7 @@ #include #include #include +#include #define MESON_SAR_ADC_REG0 0x00 #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) @@ -174,6 +175,9 @@ #define MESON_SAR_ADC_EFUSE_BYTE3_UPPER_ADC_VAL GENMASK(6, 0) #define MESON_SAR_ADC_EFUSE_BYTE3_IS_CALIBRATED BIT(7) +#define MESON_HHI_DPLL_TOP_0 0x318 +#define MESON_HHI_DPLL_TOP_0_TSC_BIT4 BIT(9) + /* for use with IIO_VAL_INT_PLUS_MICRO */ #define MILLION 1000000 @@ -280,6 +284,7 @@ struct meson_sar_adc_priv { struct completion done; int calibbias; int calibscale; + struct regmap *tsc_regmap; bool temperature_sensor_calibrated; u8 temperature_sensor_coefficient; u16 temperature_sensor_adc_val; @@ -727,6 +732,15 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev) return ret; } + priv->tsc_regmap = + syscon_regmap_lookup_by_phandle(indio_dev->dev.parent->of_node, + "amlogic,hhi-sysctrl"); + if (IS_ERR(priv->tsc_regmap)) { + dev_err(indio_dev->dev.parent, + "failed to get amlogic,hhi-sysctrl regmap\n"); + return PTR_ERR(priv->tsc_regmap); + } + read_len = MESON_SAR_ADC_EFUSE_BYTES; buf = nvmem_cell_read(temperature_calib, &read_len); if (IS_ERR(buf)) { @@ -861,6 +875,22 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) priv->temperature_sensor_coefficient); regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, MESON_SAR_ADC_DELTA_10_TS_C_MASK, regval); + + if (priv->param->temperature_trimming_bits == 5) { + if (priv->temperature_sensor_coefficient & BIT(4)) + regval = MESON_HHI_DPLL_TOP_0_TSC_BIT4; + else + regval = 0; + + /* + * bit [4] (the 5th bit when starting to count at 1) + * of the TSC is located in the HHI register area. + */ + regmap_update_bits(priv->tsc_regmap, + MESON_HHI_DPLL_TOP_0, + MESON_HHI_DPLL_TOP_0_TSC_BIT4, + regval); + } } else { regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, MESON_SAR_ADC_DELTA_10_TS_REVE1, 0); @@ -1064,6 +1094,9 @@ static const struct meson_sar_adc_param meson_sar_adc_meson8b_param = { .bandgap_reg = MESON_SAR_ADC_DELTA_10, .regmap_config = &meson_sar_adc_regmap_config_meson8, .resolution = 10, + .temperature_trimming_bits = 5, + .temperature_multiplier = 10, + .temperature_divider = 32, }; static const struct meson_sar_adc_param meson_sar_adc_gxbb_param = { -- cgit From 7fc93f3285b17f4632694efce5ff0160303388a8 Mon Sep 17 00:00:00 2001 From: Aditya Pakki Date: Thu, 27 Dec 2018 13:54:52 -0600 Subject: iio: adc: xilinx: check return value of xadc_write_adc_reg In function xadc_probe, xadc_write_adc_reg can return an error value when write fails. The fix checks for the return value consistent with other invocations of the latter function. Signed-off-by: Aditya Pakki Reviewed-by: Michal Simek Signed-off-by: Jonathan Cameron --- drivers/iio/adc/xilinx-xadc-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c index 3f6be5ac049a..b13c61539d46 100644 --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c @@ -1273,8 +1273,10 @@ static int xadc_probe(struct platform_device *pdev) xadc->threshold[i] = 0xffff; else xadc->threshold[i] = 0; - xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(i), + ret = xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(i), xadc->threshold[i]); + if (ret) + goto err_free_irq; } /* Go to non-buffered mode */ -- cgit From e9de475723de5bf207a5b7b88bdca863393e42c8 Mon Sep 17 00:00:00 2001 From: Jeremy Fertic Date: Sat, 22 Dec 2018 21:57:40 -0700 Subject: staging: iio: adt7316: fix dac_bits assignment The value of dac_bits is used in adt7316_show_DAC() and adt7316_store_DAC(), and it should be either 8, 10, or 12 bits depending on the device in use. The driver currently only assigns a value to dac_bits in adt7316_store_da_high_resolution(). The purpose of the dac high resolution option is not to change dac resolution for normal operation. Instead, it is specific to an optional feature where one or two of the four dacs can be set to output voltage proportional to temperature. If the user chooses to set dac a and/or dac b to output voltage proportional to temperature, the da_high_resolution attribute can optionally be enabled to use 10 bit resolution rather than the default 8 bits. This is only available on the 10 and 12 bit dac devices. If the user attempts to read or write dacs a or b under these settings, the driver's current behaviour is to return an error. Dacs c and d continue to operate normally under these conditions. With the above in mind, remove the dac_bits assignments from this function since the value of dac_bits as used in the driver is not dependent on this dac high resolution option. Since the dac_bits assignments discussed above are currently the only ones in this driver, the default value of dac_bits is 0. This results in incorrect calculations when the dacs are read or written in adt7316_show_DAC() and adt7316_store_DAC(). To correct this, assign a value to dac_bits in adt7316_probe() to ensure correct operation as soon as the device is registered and available to userspace. Fixes: 35f6b6b86ede ("staging: iio: new ADT7316/7/8 and ADT7516/7/9 driver") Signed-off-by: Jeremy Fertic Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 9db49aa186bb..e17c1cb12c94 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -652,17 +652,10 @@ static ssize_t adt7316_store_da_high_resolution(struct device *dev, u8 config3; int ret; - chip->dac_bits = 8; - - if (buf[0] == '1') { + if (buf[0] == '1') config3 = chip->config3 | ADT7316_DA_HIGH_RESOLUTION; - if (chip->id == ID_ADT7316 || chip->id == ID_ADT7516) - chip->dac_bits = 12; - else if (chip->id == ID_ADT7317 || chip->id == ID_ADT7517) - chip->dac_bits = 10; - } else { + else config3 = chip->config3 & (~ADT7316_DA_HIGH_RESOLUTION); - } ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3); if (ret) @@ -2145,6 +2138,13 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus, else return -ENODEV; + if (chip->id == ID_ADT7316 || chip->id == ID_ADT7516) + chip->dac_bits = 12; + else if (chip->id == ID_ADT7317 || chip->id == ID_ADT7517) + chip->dac_bits = 10; + else + chip->dac_bits = 8; + chip->ldac_pin = devm_gpiod_get_optional(dev, "adi,ldac", GPIOD_OUT_LOW); if (IS_ERR(chip->ldac_pin)) { ret = PTR_ERR(chip->ldac_pin); -- cgit From 76b7fe8d6c4daf4db672eb953c892c6f6572a282 Mon Sep 17 00:00:00 2001 From: Jeremy Fertic Date: Sat, 22 Dec 2018 21:57:41 -0700 Subject: staging: iio: adt7316: fix handling of dac high resolution option The adt7316/7 and adt7516/7 have the option to output voltage proportional to temperature on dac a and/or dac b. The default dac resolution in this mode is 8 bits with the dac high resolution option enabling 10 bits. None of these settings affect dacs c and d. Remove the "1 (12 bits)" output from the show function since that is not an option for this mode. Return "1 (10 bits)" if the device is one of the above mentioned chips and the dac high resolution mode is enabled. In the store function, the driver currently allows the user to write to the ADT7316_DA_HIGH_RESOLUTION bit regardless of the device in use. Add a check to return an error in the case of an adt7318 or adt7519. Remove the else statement that clears the ADT7316_DA_HIGH_RESOLUTION bit. Instead, clear it before conditionally enabling it, depending on user input. This matches the typical pattern in the driver when an attribute is a boolean. Fixes: 35f6b6b86ede ("staging: iio: new ADT7316/7/8 and ADT7516/7/9 driver") Signed-off-by: Jeremy Fertic Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index e17c1cb12c94..80cc3420036b 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -633,9 +633,7 @@ static ssize_t adt7316_show_da_high_resolution(struct device *dev, struct adt7316_chip_info *chip = iio_priv(dev_info); if (chip->config3 & ADT7316_DA_HIGH_RESOLUTION) { - if (chip->id == ID_ADT7316 || chip->id == ID_ADT7516) - return sprintf(buf, "1 (12 bits)\n"); - if (chip->id == ID_ADT7317 || chip->id == ID_ADT7517) + if (chip->id != ID_ADT7318 && chip->id != ID_ADT7519) return sprintf(buf, "1 (10 bits)\n"); } @@ -652,10 +650,12 @@ static ssize_t adt7316_store_da_high_resolution(struct device *dev, u8 config3; int ret; + if (chip->id == ID_ADT7318 || chip->id == ID_ADT7519) + return -EPERM; + + config3 = chip->config3 & (~ADT7316_DA_HIGH_RESOLUTION); if (buf[0] == '1') - config3 = chip->config3 | ADT7316_DA_HIGH_RESOLUTION; - else - config3 = chip->config3 & (~ADT7316_DA_HIGH_RESOLUTION); + config3 |= ADT7316_DA_HIGH_RESOLUTION; ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, config3); if (ret) -- cgit From 45130fb030aec26ac28b4bb23344901df3ec3b7f Mon Sep 17 00:00:00 2001 From: Jeremy Fertic Date: Sat, 22 Dec 2018 21:57:42 -0700 Subject: staging: iio: adt7316: fix the dac read calculation The calculation of the current dac value is using the wrong bits of the dac lsb register. Create two macros to shift the lsb register value into lsb position, depending on whether the dac is 10 or 12 bit. Initialize data to 0 so, with an 8 bit dac, the msb register value can be bitwise ORed with data. Fixes: 35f6b6b86ede ("staging: iio: new ADT7316/7/8 and ADT7516/7/9 driver") Signed-off-by: Jeremy Fertic Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 80cc3420036b..d7f3d68e525b 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -47,6 +47,8 @@ #define ADT7516_MSB_AIN3 0xA #define ADT7516_MSB_AIN4 0xB #define ADT7316_DA_DATA_BASE 0x10 +#define ADT7316_DA_10_BIT_LSB_SHIFT 6 +#define ADT7316_DA_12_BIT_LSB_SHIFT 4 #define ADT7316_DA_MSB_DATA_REGS 4 #define ADT7316_LSB_DAC_A 0x10 #define ADT7316_MSB_DAC_A 0x11 @@ -1392,7 +1394,7 @@ static IIO_DEVICE_ATTR(ex_analog_temp_offset, 0644, static ssize_t adt7316_show_DAC(struct adt7316_chip_info *chip, int channel, char *buf) { - u16 data; + u16 data = 0; u8 msb, lsb, offset; int ret; @@ -1417,7 +1419,11 @@ static ssize_t adt7316_show_DAC(struct adt7316_chip_info *chip, if (ret) return -EIO; - data = (msb << offset) + (lsb & ((1 << offset) - 1)); + if (chip->dac_bits == 12) + data = lsb >> ADT7316_DA_12_BIT_LSB_SHIFT; + else if (chip->dac_bits == 10) + data = lsb >> ADT7316_DA_10_BIT_LSB_SHIFT; + data |= msb << offset; return sprintf(buf, "%d\n", data); } -- cgit From 78accaea117c1ae878774974fab91ac4a0b0e2b0 Mon Sep 17 00:00:00 2001 From: Jeremy Fertic Date: Sat, 22 Dec 2018 21:57:43 -0700 Subject: staging: iio: adt7316: fix the dac write calculation The lsb calculation is not masking the correct bits from the user input. Subtract 1 from (1 << offset) to correctly set up the mask to be applied to user input. The lsb register stores its value starting at the bit 7 position. adt7316_store_DAC() currently assumes the value is at the other end of the register. Shift the lsb value before storing it in a new variable lsb_reg, and write this variable to the lsb register. Fixes: 35f6b6b86ede ("staging: iio: new ADT7316/7/8 and ADT7516/7/9 driver") Signed-off-by: Jeremy Fertic Signed-off-by: Jonathan Cameron --- drivers/staging/iio/addac/adt7316.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index d7f3d68e525b..6f7891b567b9 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -1431,7 +1431,7 @@ static ssize_t adt7316_show_DAC(struct adt7316_chip_info *chip, static ssize_t adt7316_store_DAC(struct adt7316_chip_info *chip, int channel, const char *buf, size_t len) { - u8 msb, lsb, offset; + u8 msb, lsb, lsb_reg, offset; u16 data; int ret; @@ -1449,9 +1449,13 @@ static ssize_t adt7316_store_DAC(struct adt7316_chip_info *chip, return -EINVAL; if (chip->dac_bits > 8) { - lsb = data & (1 << offset); + lsb = data & ((1 << offset) - 1); + if (chip->dac_bits == 12) + lsb_reg = lsb << ADT7316_DA_12_BIT_LSB_SHIFT; + else + lsb_reg = lsb << ADT7316_DA_10_BIT_LSB_SHIFT; ret = chip->bus.write(chip->bus.client, - ADT7316_DA_DATA_BASE + channel * 2, lsb); + ADT7316_DA_DATA_BASE + channel * 2, lsb_reg); if (ret) return -EIO; } -- cgit From 2f6fa4ca37c57e56ea535c947f60060c69a3dc03 Mon Sep 17 00:00:00 2001 From: Marko Stankovic Date: Tue, 25 Dec 2018 23:35:31 +0100 Subject: staging: wilc1000: make function wilc_get_stats_async static Makes local function wilc_get_stats_async() static Cleans up sparse warning: symbol 'wilc_get_stats_async' was not declared. Should it be static? Signed-off-by: Marko Stankovic 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 70c854d939ce..5dae6e7155d3 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1992,7 +1992,7 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level) return result; } -int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats) +static int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats) { int result; struct host_if_msg *msg; -- cgit From c706d4b744fb43477eeee2bb898968756e0232ad Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 26 Dec 2018 11:34:11 +0800 Subject: staging: erofs: fix return type of erofs_workgroup_get There exists a return type misuse (`int'->`bool') since all users assume it fails if only return value != 0, let's fix the return type to `int' instead of confusing `bool'. No logic changes. Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index e049d00c087a..49c587383315 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -252,7 +252,7 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) } #endif -static inline bool erofs_workgroup_get(struct erofs_workgroup *grp, int *ocnt) +static inline int erofs_workgroup_get(struct erofs_workgroup *grp, int *ocnt) { int o; -- cgit From 5777c306a42533ad17703b75dffbd17c1bd203dc Mon Sep 17 00:00:00 2001 From: Daniel Smith Date: Mon, 24 Dec 2018 10:12:23 +0000 Subject: staging: speakup: Fix coding style Replaced text ---help--- with help as per style check patch recommendation Signed-off-by: Daniel Acked-by: Samuel Thibault Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/Kconfig | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/staging/speakup/Kconfig b/drivers/staging/speakup/Kconfig index efd6f4560d3e..d8ec780f7741 100644 --- a/drivers/staging/speakup/Kconfig +++ b/drivers/staging/speakup/Kconfig @@ -3,7 +3,7 @@ menu "Speakup console speech" config SPEAKUP depends on VT tristate "Speakup core" - ---help--- + help This is the Speakup screen reader. Think of it as a video console for blind people. If built in to the kernel, it can speak everything on the text console from @@ -43,7 +43,7 @@ config SPEAKUP if SPEAKUP config SPEAKUP_SYNTH_ACNTSA tristate "Accent SA synthesizer support" - ---help--- + help This is the Speakup driver for the Accent SA synthesizer. You can say y to build it into the kernel, or m to build it as a module. See the configuration @@ -52,7 +52,7 @@ config SPEAKUP_SYNTH_ACNTSA config SPEAKUP_SYNTH_ACNTPC tristate "Accent PC synthesizer support" depends on ISA || COMPILE_TEST - ---help--- + help This is the Speakup driver for the accent pc synthesizer. You can say y to build it into the kernel, or m to build it as a module. See the configuration @@ -60,7 +60,7 @@ config SPEAKUP_SYNTH_ACNTPC config SPEAKUP_SYNTH_APOLLO tristate "Apollo II synthesizer support" - ---help--- + help This is the Speakup driver for the Apollo II synthesizer. You can say y to build it into the kernel, or m to build it as a module. See the configuration @@ -68,7 +68,7 @@ config SPEAKUP_SYNTH_APOLLO config SPEAKUP_SYNTH_AUDPTR tristate "Audapter synthesizer support" - ---help--- + help This is the Speakup driver for the Audapter synthesizer. You can say y to build it into the kernel, or m to build it as a module. See the configuration help on the @@ -76,7 +76,7 @@ config SPEAKUP_SYNTH_AUDPTR config SPEAKUP_SYNTH_BNS tristate "Braille 'n' Speak synthesizer support" - ---help--- + help This is the Speakup driver for the Braille 'n' Speak synthesizer. You can say y to build it into the kernel, or m to build it as a module. See the configuration @@ -84,7 +84,7 @@ config SPEAKUP_SYNTH_BNS config SPEAKUP_SYNTH_DECTLK tristate "DECtalk Express synthesizer support" - ---help--- + help This is the Speakup driver for the DecTalk Express synthesizer. You can say y to build it into the kernel, @@ -93,7 +93,7 @@ config SPEAKUP_SYNTH_DECTLK config SPEAKUP_SYNTH_DECEXT tristate "DECtalk External (old) synthesizer support" - ---help--- + help This is the Speakup driver for the DecTalk External (old) synthesizer. You can say y to build it into the @@ -105,7 +105,7 @@ config SPEAKUP_SYNTH_DECPC depends on m depends on ISA || COMPILE_TEST tristate "DECtalk PC (big ISA card) synthesizer support" - ---help--- + help This is the Speakup driver for the DecTalk PC (full length ISA) synthesizer. You can say m to build it as @@ -127,7 +127,7 @@ config SPEAKUP_SYNTH_DECPC config SPEAKUP_SYNTH_DTLK tristate "DoubleTalk PC synthesizer support" depends on ISA || COMPILE_TEST - ---help--- + help This is the Speakup driver for the internal DoubleTalk PC synthesizer. You can say y to build it into the @@ -138,7 +138,7 @@ config SPEAKUP_SYNTH_DTLK config SPEAKUP_SYNTH_KEYPC tristate "Keynote Gold PC synthesizer support" depends on ISA || COMPILE_TEST - ---help--- + help This is the Speakup driver for the Keynote Gold PC synthesizer. You can say y to build it into the @@ -148,7 +148,7 @@ config SPEAKUP_SYNTH_KEYPC config SPEAKUP_SYNTH_LTLK tristate "DoubleTalk LT/LiteTalk synthesizer support" ----help--- +help This is the Speakup driver for the LiteTalk/DoubleTalk LT synthesizer. You can say y to build it into the @@ -158,7 +158,7 @@ config SPEAKUP_SYNTH_LTLK config SPEAKUP_SYNTH_SOFT tristate "Userspace software synthesizer support" - ---help--- + help This is the software synthesizer device node. It will register a device /dev/softsynth which midware programs @@ -169,7 +169,7 @@ config SPEAKUP_SYNTH_SOFT config SPEAKUP_SYNTH_SPKOUT tristate "Speak Out synthesizer support" - ---help--- + help This is the Speakup driver for the Speakout synthesizer. You can say y to build it into the kernel, or m to @@ -178,7 +178,7 @@ config SPEAKUP_SYNTH_SPKOUT config SPEAKUP_SYNTH_TXPRT tristate "Transport synthesizer support" - ---help--- + help This is the Speakup driver for the Transport synthesizer. You can say y to build it into the kernel, @@ -187,7 +187,7 @@ config SPEAKUP_SYNTH_TXPRT config SPEAKUP_SYNTH_DUMMY tristate "Dummy synthesizer driver (for testing)" - ---help--- + help This is a dummy Speakup driver for plugging a mere serial terminal. This is handy if you want to test speakup but -- cgit From e062b6e572431106e06f7546de8dd31d027ea5cd Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 30 Dec 2018 16:53:12 +0100 Subject: staging: rtl8192e: reduce indentation Delete tab aligning a statement with the right hand side of a preceding assignment rather than the left hand side. Found with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/rtl_wx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c index 843e874b8a06..b798cde0ce47 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c @@ -1049,9 +1049,9 @@ static int _rtl92e_wx_set_promisc_mode(struct net_device *dev, (bPromiscuousOn) ? (true) : (false); ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame = (bFilterSourceStationFrame) ? (true) : (false); - (bPromiscuousOn) ? - (rtllib_EnableIntelPromiscuousMode(dev, false)) : - (rtllib_DisableIntelPromiscuousMode(dev, false)); + (bPromiscuousOn) ? + (rtllib_EnableIntelPromiscuousMode(dev, false)) : + (rtllib_DisableIntelPromiscuousMode(dev, false)); netdev_info(dev, "=======>%s(), on = %d, filter src sta = %d\n", -- cgit From 8f452bbb9a427420ed01993c3233df4e570f5238 Mon Sep 17 00:00:00 2001 From: William Mitchell Jr Date: Sat, 29 Dec 2018 22:14:12 -0500 Subject: staging: comedi: cb_pcimdas.c: fixed an alignment coding style issue Fixed a coding style issue. Signed-off-by: William Mitchell Jr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcimdas.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index 4e72a0778086..a9d052bfda38 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -252,9 +252,9 @@ static int cb_pcimdas_di_insn_bits(struct comedi_device *dev, } static int cb_pcimdas_do_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { struct cb_pcimdas_private *devpriv = dev->private; -- cgit From 75f3da8958d03748b5d1d743d04f64d6f6993d5f Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Thu, 20 Dec 2018 18:14:50 +0100 Subject: staging: fsl-dpaa2: fix SPDX identifiers in header files Use the correct comment style for SPDX identifiers in header files. Reported by checkpatch. Signed-off-by: Michael Straube Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 2 +- drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 2 +- drivers/staging/fsl-dpaa2/ethsw/ethsw.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h index da744f2b0ee6..14b974defa3a 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright 2014-2016 Freescale Semiconductor Inc. * Copyright 2017-2018 NXP diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h index db43fa3782b8..25635259ce44 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright 2014-2016 Freescale Semiconductor Inc. * Copyright 2017-2018 NXP diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h index 069c99bfba74..c48783680a05 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * DPAA2 Ethernet Switch declarations * -- cgit From 73b69c01cc925d9c48e5b4f78e3d8b88c4e5b924 Mon Sep 17 00:00:00 2001 From: Aditya Pakki Date: Thu, 27 Dec 2018 13:35:53 -0600 Subject: staging: rts5208: Add a check for ms_read_extra_data In ms_copy_page, the function ms_read_extra_data may fail for many reasons. The fix adds a check similar to other invocation to return error upstream. Signed-off-by: Aditya Pakki Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/ms.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index e43f92080c20..1128eec3bd08 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -1665,7 +1665,10 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, return STATUS_FAIL; } - ms_read_extra_data(chip, old_blk, i, extra, MS_EXTRA_SIZE); + retval = ms_read_extra_data(chip, old_blk, i, extra, + MS_EXTRA_SIZE); + if (retval != STATUS_SUCCESS) + return STATUS_FAIL; retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6); -- cgit From 5f98ddc9a7770c054a55bbfe925cddc8c8c30685 Mon Sep 17 00:00:00 2001 From: Himadri Pandya Date: Tue, 1 Jan 2019 06:43:19 -0800 Subject: staging: rtl8192e: rename Channel to channel style This patch fixes the checkpatch.pl warning: CHECK: Avoid CamelCase: Signed-off-by: Himadri Pandya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/dot11d.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8192e/dot11d.c b/drivers/staging/rtl8192e/dot11d.c index a1c096124683..687deac19796 100644 --- a/drivers/staging/rtl8192e/dot11d.c +++ b/drivers/staging/rtl8192e/dot11d.c @@ -15,7 +15,7 @@ #include "dot11d.h" struct channel_list { - u8 Channel[32]; + u8 channel[32]; u8 Len; }; @@ -66,11 +66,11 @@ void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee) memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map)); for (i = 0; i < ChannelPlan[channel_plan].Len; i++) { - if (ChannelPlan[channel_plan].Channel[i] < min_chan || - ChannelPlan[channel_plan].Channel[i] > max_chan) + if (ChannelPlan[channel_plan].channel[i] < min_chan || + ChannelPlan[channel_plan].channel[i] > max_chan) break; GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan - [channel_plan].Channel[i]] = 1; + [channel_plan].channel[i]] = 1; } } -- cgit From 9a47dc5f7eb3ad9a7145f43e19a2bc19b1073bfc Mon Sep 17 00:00:00 2001 From: Prathamesh Deshpande Date: Mon, 24 Dec 2018 08:53:46 -0800 Subject: staging: wlan-ng: prism2fw.c: Fix "Possible unnecessary 'out of memory' message" checkpatch.pl warning" This patch removes unnecessary out of memory warning message from wlan-ng prism2fw.c file. Signed-off-by: Prathamesh Deshpande Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2fw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index bb572b7fdfee..94800c007162 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -556,10 +556,9 @@ static int mkimage(struct imgchunk *clist, unsigned int *ccnt) /* Allocate buffer space for chunks */ for (i = 0; i < *ccnt; i++) { clist[i].data = kzalloc(clist[i].len, GFP_KERNEL); - if (!clist[i].data) { - pr_err("failed to allocate image space, exiting.\n"); + if (!clist[i].data) return 1; - } + pr_debug("chunk[%d]: addr=0x%06x len=%d\n", i, clist[i].addr, clist[i].len); } -- cgit From 0ca1f90861b6d64386261096b42bfc81ce11948a Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Fri, 4 Jan 2019 12:34:08 +0100 Subject: staging: mt7621-pinctrl: use pinconf-generic for 'dt_node_to_map' and 'dt_free_map' Instead of reimplement afunction to do 'dt_node_to_map' task like 'rt2880_pinctrl_dt_node_to_map' make use of 'pinconf_generic_dt_node_to_map_all' generic function for this task. Also use its equivalent function for free which is 'pinconf_generic_dt_free_map'. Remove 'rt2880_pinctrl_dt_node_to_map' function which is not needed anymore. This decrease a bit driver LOC and make it more generic. To properly compile this changes 'GENERIC_PINCONF' option is selected with the driver in its Kconfig file. This also fix a problem with function 'rt2880_pinctrl_dt_node_to_map' which was calling internally 'pinctrl_utils_reserve_map' which expects 'num_maps' to be initialized. It does a memory allocation based on the value, and triggers the following warning if is not properly set: if (unlikely(order >= MAX_ORDER)) { WARN_ON_ONCE(!(gfp_mask & __GFP_NOWARN)); return NULL; } Generic function 'pinconf_generic_dt_node_to_map_all' initializes properly 'num_maps' to zero fixing the problem. Fixes: e12a1a6e087b ("staging: mt7621-pinctrl: refactor rt2880_pinctrl_dt_node_to_map function") Reported-by: NeilBrown Tested-by: NeilBrown Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mt7621-pinctrl/Kconfig | 1 + drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c | 41 ++----------------------- 2 files changed, 4 insertions(+), 38 deletions(-) diff --git a/drivers/staging/mt7621-pinctrl/Kconfig b/drivers/staging/mt7621-pinctrl/Kconfig index 37cf9c3273be..fc3612711307 100644 --- a/drivers/staging/mt7621-pinctrl/Kconfig +++ b/drivers/staging/mt7621-pinctrl/Kconfig @@ -2,3 +2,4 @@ config PINCTRL_RT2880 bool "RT2800 pinctrl driver for RALINK/Mediatek SOCs" depends on RALINK select PINMUX + select GENERIC_PINCONF diff --git a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c index aa98fbb17013..80e7067cfb79 100644 --- a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c +++ b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -73,48 +74,12 @@ static int rt2880_get_group_pins(struct pinctrl_dev *pctrldev, return 0; } -static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev, - struct device_node *np_config, - struct pinctrl_map **map, - unsigned int *num_maps) -{ - struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); - struct property *prop; - const char *function_name, *group_name; - int ret; - int ngroups = 0; - unsigned int reserved_maps = 0; - - for_each_node_with_property(np_config, "group") - ngroups++; - - *map = NULL; - ret = pinctrl_utils_reserve_map(pctrldev, map, &reserved_maps, - num_maps, ngroups); - if (ret) { - dev_err(p->dev, "can't reserve map: %d\n", ret); - return ret; - } - - of_property_for_each_string(np_config, "group", prop, group_name) { - ret = pinctrl_utils_add_map_mux(pctrldev, map, &reserved_maps, - num_maps, group_name, - function_name); - if (ret) { - dev_err(p->dev, "can't add map: %d\n", ret); - return ret; - } - } - - return 0; -} - static const struct pinctrl_ops rt2880_pctrl_ops = { .get_groups_count = rt2880_get_group_count, .get_group_name = rt2880_get_group_name, .get_group_pins = rt2880_get_group_pins, - .dt_node_to_map = rt2880_pinctrl_dt_node_to_map, - .dt_free_map = pinctrl_utils_free_map, + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinconf_generic_dt_free_map, }; static int rt2880_pmx_func_count(struct pinctrl_dev *pctrldev) -- cgit From bd7c95d48854af2db899bc8b6966a0e9b9f5bf4e Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Fri, 4 Jan 2019 12:34:09 +0100 Subject: staging: mt7621-dts: use standard 'groups' instead of 'group' for pinctrl bindings Pinctrl generic functions looks for standard property 'groups' in DT to get data and use in the driver. Change all of them. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mt7621-dts/gbpc1.dts | 4 ++-- drivers/staging/mt7621-dts/mt7621.dtsi | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/staging/mt7621-dts/gbpc1.dts b/drivers/staging/mt7621-dts/gbpc1.dts index 6a1699ce9455..b73385540216 100644 --- a/drivers/staging/mt7621-dts/gbpc1.dts +++ b/drivers/staging/mt7621-dts/gbpc1.dts @@ -136,8 +136,8 @@ &pinctrl { state_default: pinctrl0 { gpio { - ralink,group = "wdt", "rgmii2", "uart3"; - ralink,function = "gpio"; + groups = "wdt", "rgmii2", "uart3"; + function = "gpio"; }; }; }; diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi index 71f069d59ad8..1cec0879e825 100644 --- a/drivers/staging/mt7621-dts/mt7621.dtsi +++ b/drivers/staging/mt7621-dts/mt7621.dtsi @@ -204,82 +204,82 @@ i2c_pins: i2c0 { i2c0 { - group = "i2c"; + groups = "i2c"; function = "i2c"; }; }; spi_pins: spi0 { spi0 { - group = "spi"; + groups = "spi"; function = "spi"; }; }; uart1_pins: uart1 { uart1 { - group = "uart1"; + groups = "uart1"; function = "uart1"; }; }; uart2_pins: uart2 { uart2 { - group = "uart2"; + groups = "uart2"; function = "uart2"; }; }; uart3_pins: uart3 { uart3 { - group = "uart3"; + groups = "uart3"; function = "uart3"; }; }; rgmii1_pins: rgmii1 { rgmii1 { - group = "rgmii1"; + groups = "rgmii1"; function = "rgmii1"; }; }; rgmii2_pins: rgmii2 { rgmii2 { - group = "rgmii2"; + groups = "rgmii2"; function = "rgmii2"; }; }; mdio_pins: mdio0 { mdio0 { - group = "mdio"; + groups = "mdio"; function = "mdio"; }; }; pcie_pins: pcie0 { pcie0 { - group = "pcie"; + groups = "pcie"; function = "pcie rst"; }; }; nand_pins: nand0 { spi-nand { - group = "spi"; + groups = "spi"; function = "nand1"; }; sdhci-nand { - group = "sdhci"; + groups = "sdhci"; function = "nand2"; }; }; sdhci_pins: sdhci0 { sdhci0 { - group = "sdhci"; + groups = "sdhci"; function = "sdhci"; }; }; -- cgit From 00981d31d6dfd0c60a3447d046205bd615ed847c Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Fri, 4 Jan 2019 08:08:21 +0100 Subject: staging: mt7621-pci-phy: add new driver for phy part of mt7621-pci Phy part of the pci for this SoC can be handled using a generic phy driver. This commit extracts phy part of the mt7621-pci into a new 'mt7621-pci-phy' driver. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/mt7621-pci-phy/Kconfig | 7 + drivers/staging/mt7621-pci-phy/Makefile | 1 + drivers/staging/mt7621-pci-phy/TODO | 4 + drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c | 387 ++++++++++++++++++++++++ 6 files changed, 402 insertions(+) create mode 100644 drivers/staging/mt7621-pci-phy/Kconfig create mode 100644 drivers/staging/mt7621-pci-phy/Makefile create mode 100644 drivers/staging/mt7621-pci-phy/TODO create mode 100644 drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index e4f608815c05..4a3d6e00f7cb 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -104,6 +104,8 @@ source "drivers/staging/pi433/Kconfig" source "drivers/staging/mt7621-pci/Kconfig" +source "drivers/staging/mt7621-pci-phy/Kconfig" + source "drivers/staging/mt7621-pinctrl/Kconfig" source "drivers/staging/mt7621-spi/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 5868631e8f1b..413890dd5a14 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo/ obj-$(CONFIG_PI433) += pi433/ obj-$(CONFIG_SOC_MT7621) += mt7621-pci/ +obj-$(CONFIG_SOC_MT7621) += mt7621-pci-phy/ obj-$(CONFIG_SOC_MT7621) += mt7621-pinctrl/ obj-$(CONFIG_SOC_MT7621) += mt7621-spi/ obj-$(CONFIG_SOC_MT7621) += mt7621-dma/ diff --git a/drivers/staging/mt7621-pci-phy/Kconfig b/drivers/staging/mt7621-pci-phy/Kconfig new file mode 100644 index 000000000000..b9f6ab784ee8 --- /dev/null +++ b/drivers/staging/mt7621-pci-phy/Kconfig @@ -0,0 +1,7 @@ +config PCI_MT7621_PHY + tristate "MediaTek MT7621 PCI PHY Driver" + depends on RALINK && OF + select GENERIC_PHY + help + Say 'Y' here to add support for MediaTek MT7621 PCI PHY driver, + diff --git a/drivers/staging/mt7621-pci-phy/Makefile b/drivers/staging/mt7621-pci-phy/Makefile new file mode 100644 index 000000000000..2b82ccfc28c6 --- /dev/null +++ b/drivers/staging/mt7621-pci-phy/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_SOC_MT7621) += pci-mt7621-phy.o diff --git a/drivers/staging/mt7621-pci-phy/TODO b/drivers/staging/mt7621-pci-phy/TODO new file mode 100644 index 000000000000..a255e8f753eb --- /dev/null +++ b/drivers/staging/mt7621-pci-phy/TODO @@ -0,0 +1,4 @@ + +- general code review and cleanup + +Cc: NeilBrown and Sergio Paracuellos diff --git a/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c new file mode 100644 index 000000000000..3d16716cfebc --- /dev/null +++ b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c @@ -0,0 +1,387 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Mediatek MT7621 PCI PHY Driver + * Author: Sergio Paracuellos + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RALINK_CLKCFG1 0x30 +#define CHIP_REV_MT7621_E2 0x0101 + +#define PCIE_PORT_CLK_EN(x) BIT(24 + (x)) + +#define RG_PE1_PIPE_REG 0x02c +#define RG_PE1_PIPE_RST BIT(12) +#define RG_PE1_PIPE_CMD_FRC BIT(4) + +#define RG_P0_TO_P1_WIDTH 0x100 +#define RG_PE1_H_LCDDS_REG 0x49c +#define RG_PE1_H_LCDDS_PCW GENMASK(30, 0) +#define RG_PE1_H_LCDDS_PCW_VAL(x) ((0x7fffffff & (x)) << 0) + +#define RG_PE1_FRC_H_XTAL_REG 0x400 +#define RG_PE1_FRC_H_XTAL_TYPE BIT(8) +#define RG_PE1_H_XTAL_TYPE GENMASK(10, 9) +#define RG_PE1_H_XTAL_TYPE_VAL(x) ((0x3 & (x)) << 9) + +#define RG_PE1_FRC_PHY_REG 0x000 +#define RG_PE1_FRC_PHY_EN BIT(4) +#define RG_PE1_PHY_EN BIT(5) + +#define RG_PE1_H_PLL_REG 0x490 +#define RG_PE1_H_PLL_BC GENMASK(23, 22) +#define RG_PE1_H_PLL_BC_VAL(x) ((0x3 & (x)) << 22) +#define RG_PE1_H_PLL_BP GENMASK(21, 18) +#define RG_PE1_H_PLL_BP_VAL(x) ((0xf & (x)) << 18) +#define RG_PE1_H_PLL_IR GENMASK(15, 12) +#define RG_PE1_H_PLL_IR_VAL(x) ((0xf & (x)) << 12) +#define RG_PE1_H_PLL_IC GENMASK(11, 8) +#define RG_PE1_H_PLL_IC_VAL(x) ((0xf & (x)) << 8) +#define RG_PE1_H_PLL_PREDIV GENMASK(7, 6) +#define RG_PE1_H_PLL_PREDIV_VAL(x) ((0x3 & (x)) << 6) +#define RG_PE1_PLL_DIVEN GENMASK(3, 1) +#define RG_PE1_PLL_DIVEN_VAL(x) ((0x7 & (x)) << 1) + +#define RG_PE1_H_PLL_FBKSEL_REG 0x4bc +#define RG_PE1_H_PLL_FBKSEL GENMASK(5, 4) +#define RG_PE1_H_PLL_FBKSEL_VAL(x) ((0x3 & (x)) << 4) + +#define RG_PE1_H_LCDDS_SSC_PRD_REG 0x4a4 +#define RG_PE1_H_LCDDS_SSC_PRD GENMASK(15, 0) +#define RG_PE1_H_LCDDS_SSC_PRD_VAL(x) ((0xffff & (x)) << 0) + +#define RG_PE1_H_LCDDS_SSC_DELTA_REG 0x4a8 +#define RG_PE1_H_LCDDS_SSC_DELTA GENMASK(11, 0) +#define RG_PE1_H_LCDDS_SSC_DELTA_VAL(x) ((0xfff & (x)) << 0) +#define RG_PE1_H_LCDDS_SSC_DELTA1 GENMASK(27, 16) +#define RG_PE1_H_LCDDS_SSC_DELTA1_VAL(x) ((0xff & (x)) << 16) + +#define RG_PE1_LCDDS_CLK_PH_INV_REG 0x4a0 +#define RG_PE1_LCDDS_CLK_PH_INV BIT(5) + +#define RG_PE1_H_PLL_BR_REG 0x4ac +#define RG_PE1_H_PLL_BR GENMASK(18, 16) +#define RG_PE1_H_PLL_BR_VAL(x) ((0x7 & (x)) << 16) + +#define RG_PE1_MSTCKDIV_REG 0x414 +#define RG_PE1_MSTCKDIV GENMASK(7, 6) +#define RG_PE1_MSTCKDIV_VAL(x) ((0x3 & (x)) << 6) + +#define RG_PE1_FRC_MSTCKDIV BIT(5) + +/** + * struct mt7621_pci_phy_instance - Mt7621 Pcie PHY device + * @phy: pointer to the kernel PHY device + * @port_base: base register + * @index: internal ID to identify the Mt7621 PCIe PHY + */ +struct mt7621_pci_phy_instance { + struct phy *phy; + void __iomem *port_base; + u32 index; +}; + +/** + * struct mt7621_pci_phy - Mt7621 Pcie PHY core + * @dev: pointer to device + * @phys: pointer to Mt7621 PHY device + * @nphys: number of PHY devices for this core + */ +struct mt7621_pci_phy { + struct device *dev; + struct mt7621_pci_phy_instance **phys; + int nphys; +}; + +static inline u32 phy_read(struct mt7621_pci_phy_instance *instance, u32 reg) +{ + return readl(instance->port_base + reg); +} + +static inline void phy_write(struct mt7621_pci_phy_instance *instance, + u32 val, u32 reg) +{ + writel(val, instance->port_base + reg); +} + +static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy, + struct mt7621_pci_phy_instance *instance) +{ + u32 offset = (instance->index != 1) ? + RG_PE1_PIPE_REG : RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH; + u32 reg; + + reg = phy_read(instance, offset); + reg &= ~(RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC); + reg |= (RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC); + phy_write(instance, reg, offset); +} + +static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy, + struct mt7621_pci_phy_instance *instance) +{ + struct device *dev = phy->dev; + u32 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0); + u32 offset; + u32 val; + + reg = (reg >> 6) & 0x7; + /* Set PCIe Port PHY to disable SSC */ + /* Debug Xtal Type */ + val = phy_read(instance, RG_PE1_FRC_H_XTAL_REG); + val &= ~(RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE); + val |= RG_PE1_FRC_H_XTAL_TYPE; + val |= RG_PE1_H_XTAL_TYPE_VAL(0x00); + phy_write(instance, val, RG_PE1_FRC_H_XTAL_REG); + + /* disable port */ + offset = (instance->index != 1) ? + RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH; + val = phy_read(instance, offset); + val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN); + val |= RG_PE1_FRC_PHY_EN; + phy_write(instance, val, offset); + + /* Set Pre-divider ratio (for host mode) */ + val = phy_read(instance, RG_PE1_H_PLL_REG); + val &= ~(RG_PE1_H_PLL_PREDIV); + + if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */ + val |= RG_PE1_H_PLL_PREDIV_VAL(0x01); + phy_write(instance, val, RG_PE1_H_PLL_REG); + dev_info(dev, "Xtal is 40MHz\n"); + } else { /* 25MHz | 20MHz Xtal */ + val |= RG_PE1_H_PLL_PREDIV_VAL(0x00); + phy_write(instance, val, RG_PE1_H_PLL_REG); + if (reg >= 6) { + dev_info(dev, "Xtal is 25MHz\n"); + + /* Select feedback clock */ + val = phy_read(instance, RG_PE1_H_PLL_FBKSEL_REG); + val &= ~(RG_PE1_H_PLL_FBKSEL); + val |= RG_PE1_H_PLL_FBKSEL_VAL(0x01); + phy_write(instance, val, RG_PE1_H_PLL_FBKSEL_REG); + + /* DDS NCPO PCW (for host mode) */ + val = phy_read(instance, RG_PE1_H_LCDDS_SSC_PRD_REG); + val &= ~(RG_PE1_H_LCDDS_SSC_PRD); + val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18000000); + phy_write(instance, val, RG_PE1_H_LCDDS_SSC_PRD_REG); + + /* DDS SSC dither period control */ + val = phy_read(instance, RG_PE1_H_LCDDS_SSC_PRD_REG); + val &= ~(RG_PE1_H_LCDDS_SSC_PRD); + val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18d); + phy_write(instance, val, RG_PE1_H_LCDDS_SSC_PRD_REG); + + /* DDS SSC dither amplitude control */ + val = phy_read(instance, RG_PE1_H_LCDDS_SSC_DELTA_REG); + val &= ~(RG_PE1_H_LCDDS_SSC_DELTA | + RG_PE1_H_LCDDS_SSC_DELTA1); + val |= RG_PE1_H_LCDDS_SSC_DELTA_VAL(0x4a); + val |= RG_PE1_H_LCDDS_SSC_DELTA1_VAL(0x4a); + phy_write(instance, val, RG_PE1_H_LCDDS_SSC_DELTA_REG); + } else { + dev_info(dev, "Xtal is 20MHz\n"); + } + } + + /* DDS clock inversion */ + val = phy_read(instance, RG_PE1_LCDDS_CLK_PH_INV_REG); + val &= ~(RG_PE1_LCDDS_CLK_PH_INV); + val |= RG_PE1_LCDDS_CLK_PH_INV; + phy_write(instance, val, RG_PE1_LCDDS_CLK_PH_INV_REG); + + /* Set PLL bits */ + val = phy_read(instance, RG_PE1_H_PLL_REG); + val &= ~(RG_PE1_H_PLL_BC | RG_PE1_H_PLL_BP | RG_PE1_H_PLL_IR | + RG_PE1_H_PLL_IC | RG_PE1_PLL_DIVEN); + val |= RG_PE1_H_PLL_BC_VAL(0x02); + val |= RG_PE1_H_PLL_BP_VAL(0x06); + val |= RG_PE1_H_PLL_IR_VAL(0x02); + val |= RG_PE1_H_PLL_IC_VAL(0x01); + val |= RG_PE1_PLL_DIVEN_VAL(0x02); + phy_write(instance, val, RG_PE1_H_PLL_REG); + + val = phy_read(instance, RG_PE1_H_PLL_BR_REG); + val &= ~(RG_PE1_H_PLL_BR); + val |= RG_PE1_H_PLL_BR_VAL(0x00); + phy_write(instance, val, RG_PE1_H_PLL_BR_REG); + + if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */ + /* set force mode enable of da_pe1_mstckdiv */ + val = phy_read(instance, RG_PE1_MSTCKDIV_REG); + val &= ~(RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV); + val |= (RG_PE1_MSTCKDIV_VAL(0x01) | RG_PE1_FRC_MSTCKDIV); + phy_write(instance, val, RG_PE1_MSTCKDIV_REG); + } +} + +static int mt7621_pci_phy_init(struct phy *phy) +{ + struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy); + struct mt7621_pci_phy *mphy = dev_get_drvdata(phy->dev.parent); + u32 chip_rev_id = rt_sysc_r32(SYSC_REG_CHIP_REV); + + if ((chip_rev_id & 0xFFFF) == CHIP_REV_MT7621_E2) + mt7621_bypass_pipe_rst(mphy, instance); + + mt7621_set_phy_for_ssc(mphy, instance); + + return 0; +} + +static int mt7621_pci_phy_power_on(struct phy *phy) +{ + struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy); + u32 offset = (instance->index != 1) ? + RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH; + u32 val; + + /* Enable PHY and disable force mode */ + val = phy_read(instance, offset); + val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN); + val |= (RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN); + phy_write(instance, val, offset); + + return 0; +} + +static int mt7621_pci_phy_power_off(struct phy *phy) +{ + struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy); + u32 offset = (instance->index != 1) ? + RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH; + u32 val; + + /* Disable PHY */ + val = phy_read(instance, offset); + val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN); + val |= RG_PE1_FRC_PHY_EN; + phy_write(instance, val, offset); + + return 0; +} + +static int mt7621_pci_phy_exit(struct phy *phy) +{ + struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy); + + rt_sysc_m32(PCIE_PORT_CLK_EN(instance->index), 0, RALINK_CLKCFG1); + + return 0; +} + +static const struct phy_ops mt7621_pci_phy_ops = { + .init = mt7621_pci_phy_init, + .exit = mt7621_pci_phy_exit, + .power_on = mt7621_pci_phy_power_on, + .power_off = mt7621_pci_phy_power_off, + .owner = THIS_MODULE, +}; + +static int mt7621_pci_phy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *child_np; + struct phy_provider *provider; + struct mt7621_pci_phy *phy; + struct resource res; + int port, ret; + void __iomem *port_base; + + phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + + phy->nphys = of_get_child_count(np); + phy->phys = devm_kcalloc(dev, phy->nphys, + sizeof(*phy->phys), GFP_KERNEL); + if (!phy->phys) + return -ENOMEM; + + phy->dev = dev; + platform_set_drvdata(pdev, phy); + + ret = of_address_to_resource(np, 0, &res); + if (ret) { + dev_err(dev, "failed to get address resource(id-%d)\n", port); + return ret; + } + + port_base = devm_ioremap_resource(dev, &res); + if (IS_ERR(port_base)) { + dev_err(dev, "failed to remap phy regs\n"); + return PTR_ERR(port_base); + } + + port = 0; + for_each_child_of_node(np, child_np) { + struct mt7621_pci_phy_instance *instance; + struct phy *pphy; + + instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL); + if (!instance) { + ret = -ENOMEM; + goto put_child; + } + + phy->phys[port] = instance; + + pphy = devm_phy_create(dev, child_np, &mt7621_pci_phy_ops); + if (IS_ERR(phy)) { + dev_err(dev, "failed to create phy\n"); + ret = PTR_ERR(phy); + goto put_child; + } + + instance->port_base = port_base; + instance->phy = pphy; + instance->index = port; + phy_set_drvdata(pphy, instance); + port++; + } + + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(provider); + +put_child: + of_node_put(child_np); + return ret; +} + +static const struct of_device_id mt7621_pci_phy_ids[] = { + { .compatible = "mediatek,mt7621-pci-phy" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mt7621_pci_ids); + +static struct platform_driver mt7621_pci_phy_driver = { + .probe = mt7621_pci_phy_probe, + .driver = { + .name = "mt7621-pci-phy", + .of_match_table = of_match_ptr(mt7621_pci_phy_ids), + }, +}; + +static int __init mt7621_pci_phy_drv_init(void) +{ + return platform_driver_register(&mt7621_pci_phy_driver); +} + +arch_initcall(mt7621_pci_phy_drv_init); + +MODULE_AUTHOR("Sergio Paracuellos "); +MODULE_DESCRIPTION("MediaTek MT7621 PCIe PHY driver"); +MODULE_LICENSE("GPL v2"); -- cgit From 61f9bde6ea578f5baa1662c97365f7b36fc790fa Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Fri, 4 Jan 2019 08:08:22 +0100 Subject: staging: mt7621-pci: handle phy using new generic phy 'pci-mt7621-phy' driver Phy part of this driver has been moved to a new 'pci-mt7621-phy' driver. Change code to use kernel's generic phy API removing also no more need moved code. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mt7621-pci/pci-mt7621.c | 250 ++++---------------------------- 1 file changed, 32 insertions(+), 218 deletions(-) diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c index 31310b6fb7db..8db94fdbdd6d 100644 --- a/drivers/staging/mt7621-pci/pci-mt7621.c +++ b/drivers/staging/mt7621-pci/pci-mt7621.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -95,76 +96,12 @@ #define RALINK_PCI_IO_MAP_BASE 0x1e160000 #define MEMORY_BASE 0x0 -/* pcie phy related macros */ -#define RALINK_PCIEPHY_P0P1_CTL_OFFSET 0x9000 -#define RALINK_PCIEPHY_P2_CTL_OFFSET 0xA000 - -#define RG_P0_TO_P1_WIDTH 0x100 - -#define RG_PE1_PIPE_REG 0x02c -#define RG_PE1_PIPE_RST BIT(12) -#define RG_PE1_PIPE_CMD_FRC BIT(4) - -#define RG_PE1_H_LCDDS_REG 0x49c -#define RG_PE1_H_LCDDS_PCW GENMASK(30, 0) -#define RG_PE1_H_LCDDS_PCW_VAL(x) ((0x7fffffff & (x)) << 0) - -#define RG_PE1_FRC_H_XTAL_REG 0x400 -#define RG_PE1_FRC_H_XTAL_TYPE BIT(8) -#define RG_PE1_H_XTAL_TYPE GENMASK(10, 9) -#define RG_PE1_H_XTAL_TYPE_VAL(x) ((0x3 & (x)) << 9) - -#define RG_PE1_FRC_PHY_REG 0x000 -#define RG_PE1_FRC_PHY_EN BIT(4) -#define RG_PE1_PHY_EN BIT(5) - -#define RG_PE1_H_PLL_REG 0x490 -#define RG_PE1_H_PLL_BC GENMASK(23, 22) -#define RG_PE1_H_PLL_BC_VAL(x) ((0x3 & (x)) << 22) -#define RG_PE1_H_PLL_BP GENMASK(21, 18) -#define RG_PE1_H_PLL_BP_VAL(x) ((0xf & (x)) << 18) -#define RG_PE1_H_PLL_IR GENMASK(15, 12) -#define RG_PE1_H_PLL_IR_VAL(x) ((0xf & (x)) << 12) -#define RG_PE1_H_PLL_IC GENMASK(11, 8) -#define RG_PE1_H_PLL_IC_VAL(x) ((0xf & (x)) << 8) -#define RG_PE1_H_PLL_PREDIV GENMASK(7, 6) -#define RG_PE1_H_PLL_PREDIV_VAL(x) ((0x3 & (x)) << 6) -#define RG_PE1_PLL_DIVEN GENMASK(3, 1) -#define RG_PE1_PLL_DIVEN_VAL(x) ((0x7 & (x)) << 1) - -#define RG_PE1_H_PLL_FBKSEL_REG 0x4bc -#define RG_PE1_H_PLL_FBKSEL GENMASK(5, 4) -#define RG_PE1_H_PLL_FBKSEL_VAL(x) ((0x3 & (x)) << 4) - -#define RG_PE1_H_LCDDS_SSC_PRD_REG 0x4a4 -#define RG_PE1_H_LCDDS_SSC_PRD GENMASK(15, 0) -#define RG_PE1_H_LCDDS_SSC_PRD_VAL(x) ((0xffff & (x)) << 0) - -#define RG_PE1_H_LCDDS_SSC_DELTA_REG 0x4a8 -#define RG_PE1_H_LCDDS_SSC_DELTA GENMASK(11, 0) -#define RG_PE1_H_LCDDS_SSC_DELTA_VAL(x) ((0xfff & (x)) << 0) -#define RG_PE1_H_LCDDS_SSC_DELTA1 GENMASK(27, 16) -#define RG_PE1_H_LCDDS_SSC_DELTA1_VAL(x) ((0xff & (x)) << 16) - -#define RG_PE1_LCDDS_CLK_PH_INV_REG 0x4a0 -#define RG_PE1_LCDDS_CLK_PH_INV BIT(5) - -#define RG_PE1_H_PLL_BR_REG 0x4ac -#define RG_PE1_H_PLL_BR GENMASK(18, 16) -#define RG_PE1_H_PLL_BR_VAL(x) ((0x7 & (x)) << 16) - -#define RG_PE1_MSTCKDIV_REG 0x414 -#define RG_PE1_MSTCKDIV GENMASK(7, 6) -#define RG_PE1_MSTCKDIV_VAL(x) ((0x3 & (x)) << 6) - -#define RG_PE1_FRC_MSTCKDIV BIT(5) - /** * struct mt7621_pcie_port - PCIe port information * @base: I/O mapped register base * @list: port list * @pcie: pointer to PCIe host info - * @phy_reg_offset: offset to related phy registers + * @phy: pointer to PHY control block * @pcie_rst: pointer to port reset control * @slot: port slot * @enabled: indicates if port is enabled @@ -173,7 +110,7 @@ struct mt7621_pcie_port { void __iomem *base; struct list_head list; struct mt7621_pcie *pcie; - u32 phy_reg_offset; + struct phy *phy; struct reset_control *pcie_rst; u32 slot; bool enabled; @@ -265,150 +202,6 @@ static void write_config(struct mt7621_pcie *pcie, unsigned int dev, pcie_write(pcie, val, RALINK_PCI_CONFIG_DATA); } -static void bypass_pipe_rst(struct mt7621_pcie_port *port) -{ - struct mt7621_pcie *pcie = port->pcie; - u32 phy_offset = port->phy_reg_offset; - u32 offset = (port->slot != 1) ? - phy_offset + RG_PE1_PIPE_REG : - phy_offset + RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH; - u32 reg = pcie_read(pcie, offset); - - reg &= ~(RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC); - reg |= (RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC); - pcie_write(pcie, reg, offset); -} - -static void set_phy_for_ssc(struct mt7621_pcie_port *port) -{ - struct mt7621_pcie *pcie = port->pcie; - struct device *dev = pcie->dev; - u32 phy_offset = port->phy_reg_offset; - u32 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0); - u32 offset; - u32 val; - - reg = (reg >> 6) & 0x7; - /* Set PCIe Port PHY to disable SSC */ - /* Debug Xtal Type */ - offset = phy_offset + RG_PE1_FRC_H_XTAL_REG; - val = pcie_read(pcie, offset); - val &= ~(RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE); - val |= RG_PE1_FRC_H_XTAL_TYPE; - val |= RG_PE1_H_XTAL_TYPE_VAL(0x00); - pcie_write(pcie, val, offset); - - /* disable port */ - offset = (port->slot != 1) ? - phy_offset + RG_PE1_FRC_PHY_REG : - phy_offset + RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH; - val = pcie_read(pcie, offset); - val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN); - val |= RG_PE1_FRC_PHY_EN; - pcie_write(pcie, val, offset); - - /* Set Pre-divider ratio (for host mode) */ - offset = phy_offset + RG_PE1_H_PLL_REG; - val = pcie_read(pcie, offset); - val &= ~(RG_PE1_H_PLL_PREDIV); - - if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */ - val |= RG_PE1_H_PLL_PREDIV_VAL(0x01); - pcie_write(pcie, val, offset); - dev_info(dev, "Xtal is 40MHz\n"); - } else { /* 25MHz | 20MHz Xtal */ - val |= RG_PE1_H_PLL_PREDIV_VAL(0x00); - pcie_write(pcie, val, offset); - if (reg >= 6) { - dev_info(dev, "Xtal is 25MHz\n"); - - /* Select feedback clock */ - offset = phy_offset + RG_PE1_H_PLL_FBKSEL_REG; - val = pcie_read(pcie, offset); - val &= ~(RG_PE1_H_PLL_FBKSEL); - val |= RG_PE1_H_PLL_FBKSEL_VAL(0x01); - pcie_write(pcie, val, offset); - - /* DDS NCPO PCW (for host mode) */ - offset = phy_offset + RG_PE1_H_LCDDS_SSC_PRD_REG; - val = pcie_read(pcie, offset); - val &= ~(RG_PE1_H_LCDDS_SSC_PRD); - val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18000000); - pcie_write(pcie, val, offset); - - /* DDS SSC dither period control */ - offset = phy_offset + RG_PE1_H_LCDDS_SSC_PRD_REG; - val = pcie_read(pcie, offset); - val &= ~(RG_PE1_H_LCDDS_SSC_PRD); - val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18d); - pcie_write(pcie, val, offset); - - /* DDS SSC dither amplitude control */ - offset = phy_offset + RG_PE1_H_LCDDS_SSC_DELTA_REG; - val = pcie_read(pcie, offset); - val &= ~(RG_PE1_H_LCDDS_SSC_DELTA | - RG_PE1_H_LCDDS_SSC_DELTA1); - val |= RG_PE1_H_LCDDS_SSC_DELTA_VAL(0x4a); - val |= RG_PE1_H_LCDDS_SSC_DELTA1_VAL(0x4a); - pcie_write(pcie, val, offset); - } else { - dev_info(dev, "Xtal is 20MHz\n"); - } - } - - /* DDS clock inversion */ - offset = phy_offset + RG_PE1_LCDDS_CLK_PH_INV_REG; - val = pcie_read(pcie, offset); - val &= ~(RG_PE1_LCDDS_CLK_PH_INV); - val |= RG_PE1_LCDDS_CLK_PH_INV; - pcie_write(pcie, val, offset); - - /* Set PLL bits */ - offset = phy_offset + RG_PE1_H_PLL_REG; - val = pcie_read(pcie, offset); - val &= ~(RG_PE1_H_PLL_BC | RG_PE1_H_PLL_BP | RG_PE1_H_PLL_IR | - RG_PE1_H_PLL_IC | RG_PE1_PLL_DIVEN); - val |= RG_PE1_H_PLL_BC_VAL(0x02); - val |= RG_PE1_H_PLL_BP_VAL(0x06); - val |= RG_PE1_H_PLL_IR_VAL(0x02); - val |= RG_PE1_H_PLL_IC_VAL(0x01); - val |= RG_PE1_PLL_DIVEN_VAL(0x02); - pcie_write(pcie, val, offset); - - offset = phy_offset + RG_PE1_H_PLL_BR_REG; - val = pcie_read(pcie, offset); - val &= ~(RG_PE1_H_PLL_BR); - val |= RG_PE1_H_PLL_BR_VAL(0x00); - pcie_write(pcie, val, offset); - - if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */ - /* set force mode enable of da_pe1_mstckdiv */ - offset = phy_offset + RG_PE1_MSTCKDIV_REG; - val = pcie_read(pcie, offset); - val &= ~(RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV); - val |= (RG_PE1_MSTCKDIV_VAL(0x01) | RG_PE1_FRC_MSTCKDIV); - pcie_write(pcie, val, offset); - } - - /* Enable PHY and disable force mode */ - offset = (port->slot != 1) ? - phy_offset + RG_PE1_FRC_PHY_REG : - phy_offset + RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH; - val = pcie_read(pcie, offset); - val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN); - val |= (RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN); - pcie_write(pcie, val, offset); -} - -static void mt7621_enable_phy(struct mt7621_pcie_port *port) -{ - u32 chip_rev_id = rt_sysc_r32(MT7621_CHIP_REV_ID); - - if ((chip_rev_id & 0xFFFF) == CHIP_REV_MT7621_E2) - bypass_pipe_rst(port); - set_phy_for_ssc(port); -} - static inline void mt7621_control_assert(struct mt7621_pcie_port *port) { u32 chip_rev_id = rt_sysc_r32(MT7621_CHIP_REV_ID); @@ -510,7 +303,7 @@ static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie, struct device *dev = pcie->dev; struct device_node *pnode = dev->of_node; struct resource regs; - char name[6]; + char name[10]; int err; port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); @@ -534,11 +327,13 @@ static int mt7621_pcie_parse_port(struct mt7621_pcie *pcie, return PTR_ERR(port->pcie_rst); } + snprintf(name, sizeof(name), "pcie-phy%d", slot); + port->phy = devm_phy_get(dev, name); + if (IS_ERR(port->phy)) + return PTR_ERR(port->phy); + port->slot = slot; port->pcie = pcie; - port->phy_reg_offset = (slot != 2) ? - RALINK_PCIEPHY_P0P1_CTL_OFFSET : - RALINK_PCIEPHY_P2_CTL_OFFSET; INIT_LIST_HEAD(&port->list); list_add_tail(&port->list, &pcie->ports); @@ -588,6 +383,7 @@ static int mt7621_pcie_init_port(struct mt7621_pcie_port *port) struct device *dev = pcie->dev; u32 slot = port->slot; u32 val = 0; + int err; /* * Any MT7621 Ralink pcie controller that doesn't have 0x0101 at @@ -598,18 +394,36 @@ static int mt7621_pcie_init_port(struct mt7621_pcie_port *port) val = read_config(pcie, slot, PCIE_FTS_NUM); dev_info(dev, "Port %d N_FTS = %x\n", (unsigned int)val, slot); + err = phy_init(port->phy); + if (err) { + dev_err(dev, "failed to initialize port%d phy\n", slot); + goto err_phy_init; + } + + err = phy_power_on(port->phy); + if (err) { + dev_err(dev, "failed to power on port%d phy\n", slot); + goto err_phy_on; + } + if ((pcie_port_read(port, RALINK_PCI_STATUS) & PCIE_PORT_LINKUP) == 0) { dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n", slot); mt7621_control_assert(port); - rt_sysc_m32(PCIE_PORT_CLK_EN(slot), 0, RALINK_CLKCFG1); port->enabled = false; - } else { - port->enabled = true; + err = -ENODEV; + goto err_no_link_up; } - mt7621_enable_phy(port); + port->enabled = true; return 0; + +err_no_link_up: + phy_power_off(port->phy); +err_phy_on: + phy_exit(port->phy); +err_phy_init: + return err; } static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie) -- cgit From 06184ba5a33a16f1772857d2cf97f7f14c8018c7 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Fri, 4 Jan 2019 08:08:23 +0100 Subject: staging: mt7621-dts: add pci-phy related bindings to board's device tree New driver for pci phy has been added, as well as. pci driver has been changed to use kernel's generic PHY API. Add related PCI PHY bindings accordly. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mt7621-dts/mt7621.dtsi | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi index 1cec0879e825..f0c51622eca1 100644 --- a/drivers/staging/mt7621-dts/mt7621.dtsi +++ b/drivers/staging/mt7621-dts/mt7621.dtsi @@ -424,6 +424,8 @@ reset-names = "pcie0", "pcie1", "pcie2"; clocks = <&clkctrl 24 &clkctrl 25 &clkctrl 26>; clock-names = "pcie0", "pcie1", "pcie2"; + phys = <&pcie0_port>, <&pcie1_port>, <&pcie2_port>; + phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2"; pcie@0,0 { reg = <0x0000 0 0 0 0>; @@ -449,4 +451,33 @@ bus-range = <0x00 0xff>; }; }; + + pcie0_phy: pcie-phy@1a149000 { + compatible = "mediatek,mt7621-pci-phy"; + reg = <0x1a149000 0x0700>; + #address-cells = <1>; + #size-cells = <0>; + + pcie0_port: pcie-phy@0 { + reg = <0>; + #phy-cells = <0>; + }; + + pcie1_port: pcie-phy@1 { + reg = <1>; + #phy-cells = <0>; + }; + }; + + pcie1_phy: pcie-phy@1a14a000 { + compatible = "mediatek,mt7621-pci-phy"; + reg = <0x1a14a000 0x0700>; + #address-cells = <1>; + #size-cells = <0>; + + pcie2_port: pcie-phy@0 { + reg = <0>; + #phy-cells = <0>; + }; + }; }; -- cgit From 9e2ddbdd9218bf0e465d19daecdd053052ffd79c Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Fri, 4 Jan 2019 08:08:24 +0100 Subject: staging: mt7621-pci-phy: dt-bindings: add bindings for Mediatek MT7621 Pcie PHY Add bindings documentation for PCie PHY of Mediatek MT7621. This file will be moved into its appropiate documentation bindings'place when this driver is mainlined. CC: Device Tree mailing list Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- .../mt7621-pci-phy/mediatek,mt7621-pci-phy.txt | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt diff --git a/drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt b/drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt new file mode 100644 index 000000000000..33a8a698bdd0 --- /dev/null +++ b/drivers/staging/mt7621-pci-phy/mediatek,mt7621-pci-phy.txt @@ -0,0 +1,54 @@ +Mediatek Mt7621 PCIe PHY + +Required properties: +- compatible: must be "mediatek,mt7621-pci-phy" +- reg: base address and length of the PCIe PHY block +- #address-cells: must be 1 +- #size-cells: must be 0 + +Each PCIe PHY should be represented by a child node + +Required properties For the child node: +- reg: the PHY ID +0 - PCIe RC 0 +1 - PCIe RC 1 +- #phy-cells: must be 0 + +Example: + pcie0_phy: pcie-phy@1a149000 { + compatible = "mediatek,mt7621-pci-phy"; + reg = <0x1a149000 0x0700>; + #address-cells = <1>; + #size-cells = <0>; + + pcie0_port: pcie-phy@0 { + reg = <0>; + #phy-cells = <0>; + }; + + pcie1_port: pcie-phy@1 { + reg = <1>; + #phy-cells = <0>; + }; + }; + + pcie1_phy: pcie-phy@1a14a000 { + compatible = "mediatek,mt7621-pci-phy"; + reg = <0x1a14a000 0x0700>; + #address-cells = <1>; + #size-cells = <0>; + + pcie2_port: pcie-phy@0 { + reg = <0>; + #phy-cells = <0>; + }; + }; + + /* users of the PCIe phy */ + + pcie: pcie@1e140000 { + ... + ... + phys = <&pcie0_port>, <&pcie1_port>, <&pcie2_port>; + phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2"; + }; \ No newline at end of file -- cgit From 037e9edf9d058f68ec33ec518e41c63949f84a0c Mon Sep 17 00:00:00 2001 From: Matteo Croce Date: Fri, 4 Jan 2019 22:50:12 +0100 Subject: staging: comedi: fix typo Fix spelling mistake: "lenghth" -> "length" Signed-off-by: Matteo Croce Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxfast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index e18c0723b760..0d54f394dbd2 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -61,7 +61,7 @@ #define USBDUXFASTSUB_CPUCS 0xE600 /* - * max lenghth of the transfer-buffer for software upload + * max length of the transfer-buffer for software upload */ #define TB_LEN 0x2000 -- cgit From 045ee2d0d0757b02f7a8897c26bed3dc127aa564 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 4 Jan 2019 15:30:47 -0600 Subject: staging: mt7621-dma: Use struct_size() in devm_kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; instance = devm_kzalloc(dev, sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = devm_kzalloc(dev, struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mt7621-dma/ralink-gdma.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/mt7621-dma/ralink-gdma.c b/drivers/staging/mt7621-dma/ralink-gdma.c index 792a63bd55d4..d78042eba6dd 100644 --- a/drivers/staging/mt7621-dma/ralink-gdma.c +++ b/drivers/staging/mt7621-dma/ralink-gdma.c @@ -821,9 +821,9 @@ static int gdma_dma_probe(struct platform_device *pdev) return -EINVAL; data = (struct gdma_data *) match->data; - dma_dev = devm_kzalloc(&pdev->dev, sizeof(*dma_dev) + - (sizeof(struct gdma_dmaengine_chan) * data->chancnt), - GFP_KERNEL); + dma_dev = devm_kzalloc(&pdev->dev, + struct_size(dma_dev, chan, data->chancnt), + GFP_KERNEL); if (!dma_dev) { dev_err(&pdev->dev, "alloc dma device failed\n"); return -EINVAL; -- cgit From c8c2702409430a6a2fd928e857f15773aaafcc99 Mon Sep 17 00:00:00 2001 From: Aditya Pakki Date: Sat, 5 Jan 2019 08:14:41 -0600 Subject: Staging: rts5208: Fix error handling on rtsx_send_cmd In sd_execute_write_data, the rtsx_send_cmd could fail with ETIMEDOUT or EIO. The fix adds a check to handle these failures. Signed-off-by: Aditya Pakki Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/sd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index 2c47ae613ea1..c256a2398651 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -4437,7 +4437,12 @@ int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip) rtsx_init_cmd(chip); rtsx_add_cmd(chip, CHECK_REG_CMD, 0xFD30, 0x02, 0x02); - rtsx_send_cmd(chip, SD_CARD, 250); + retval = rtsx_send_cmd(chip, SD_CARD, 250); + if (retval < 0) { + write_err = true; + rtsx_clear_sd_error(chip); + goto sd_execute_write_cmd_failed; + } retval = sd_update_lock_status(chip); if (retval != STATUS_SUCCESS) { -- cgit From 0a64d62d5399ee7881884704fe9848a791c4bac6 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Tue, 8 Jan 2019 11:31:47 +0000 Subject: staging: erofs: fixed -Wmissing-prototype warnings by making functions static. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define three functions which are not used outside their own translation-units as static in order to fix the following warnings: drivers/staging/erofs/utils.c:134:6: warning: no previous prototype for ‘erofs_try_to_release_workgroup’ [-Wmissing-prototypes] bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/staging/erofs/unzip_vle.c:592:6: warning: no previous prototype for ‘z_erofs_vle_work_release’ [-Wmissing-prototypes] void z_erofs_vle_work_release(struct z_erofs_vle_work *work) ^~~~~~~~~~~~~~~~~~~~~~~~ drivers/staging/erofs/unzip_vle_lz4.c:16:5: warning: no previous prototype for ‘z_erofs_unzip_lz4’ [-Wmissing-prototypes] int z_erofs_unzip_lz4(void *in, void *out, size_t inlen, size_t outlen) ^~~~~~~~~~~~~~~~~ Signed-off-by: Jeremy Sowden Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/unzip_vle.c | 2 +- drivers/staging/erofs/unzip_vle_lz4.c | 2 +- drivers/staging/erofs/utils.c | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c index 4ac1099a39c6..584612b47369 100644 --- a/drivers/staging/erofs/unzip_vle.c +++ b/drivers/staging/erofs/unzip_vle.c @@ -589,7 +589,7 @@ static void __z_erofs_vle_work_release(struct z_erofs_vle_workgroup *grp, erofs_workgroup_put(&grp->obj); } -void z_erofs_vle_work_release(struct z_erofs_vle_work *work) +static void z_erofs_vle_work_release(struct z_erofs_vle_work *work) { struct z_erofs_vle_workgroup *grp = z_erofs_vle_work_workgroup(work, true); diff --git a/drivers/staging/erofs/unzip_vle_lz4.c b/drivers/staging/erofs/unzip_vle_lz4.c index 52797bd89da1..8e8d705a6861 100644 --- a/drivers/staging/erofs/unzip_vle_lz4.c +++ b/drivers/staging/erofs/unzip_vle_lz4.c @@ -13,7 +13,7 @@ #include "unzip_vle.h" #include -int z_erofs_unzip_lz4(void *in, void *out, size_t inlen, size_t outlen) +static int z_erofs_unzip_lz4(void *in, void *out, size_t inlen, size_t outlen) { int ret = LZ4_decompress_safe_partial(in, out, inlen, outlen, outlen); diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index b535898ca753..fc30025ef101 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -131,9 +131,9 @@ static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp) __erofs_workgroup_free(grp); } -bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, - struct erofs_workgroup *grp, - bool cleanup) +static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, + struct erofs_workgroup *grp, + bool cleanup) { /* * for managed cache enabled, the refcount of workgroups @@ -172,9 +172,9 @@ bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, #else /* for nocache case, no customized reclaim path at all */ -bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, - struct erofs_workgroup *grp, - bool cleanup) +static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, + struct erofs_workgroup *grp, + bool cleanup) { int cnt = atomic_read(&grp->refcount); -- cgit From e7dfb1cff65b1ac6f1175f3080f6b74272f338f1 Mon Sep 17 00:00:00 2001 From: Jeremy Sowden Date: Tue, 8 Jan 2019 11:31:48 +0000 Subject: staging: erofs: fixed -Wmissing-prototype warnings by moving prototypes to header file. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moved prototypes for two functions to a header file in order to fix the following warnings: drivers/staging/erofs/unzip_vle.c:577:6: warning: no previous prototype for ‘erofs_workgroup_free_rcu’ [-Wmissing-prototypes] void erofs_workgroup_free_rcu(struct erofs_workgroup *grp) ^~~~~~~~~~~~~~~~~~~~~~~~ drivers/staging/erofs/unzip_vle.c:1702:5: warning: no previous prototype for ‘z_erofs_map_blocks_iter’ [-Wmissing-prototypes] int z_erofs_map_blocks_iter(struct inode *inode, ^~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Jeremy Sowden Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/data.c | 6 ------ drivers/staging/erofs/internal.h | 7 +++++++ drivers/staging/erofs/utils.c | 2 -- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/staging/erofs/data.c b/drivers/staging/erofs/data.c index 5a55f0bfdfbb..329fa4fa3e9c 100644 --- a/drivers/staging/erofs/data.c +++ b/drivers/staging/erofs/data.c @@ -165,12 +165,6 @@ err_out: return err; } -#ifdef CONFIG_EROFS_FS_ZIP -extern int z_erofs_map_blocks_iter(struct inode *, - struct erofs_map_blocks *, - struct page **, int); -#endif - int erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, struct page **mpage_ret, int flags) diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 49c587383315..192f4028d85d 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -288,6 +288,8 @@ static inline void erofs_workstation_cleanup_all(struct super_block *sb) erofs_shrink_workstation(EROFS_SB(sb), ~0UL, true); } +extern void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); + #ifdef EROFS_FS_HAS_MANAGED_CACHE extern int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, struct erofs_workgroup *egrp); @@ -530,6 +532,11 @@ struct erofs_map_blocks_iter { struct page *mpage; }; +#ifdef CONFIG_EROFS_FS_ZIP +extern int z_erofs_map_blocks_iter(struct inode *, + struct erofs_map_blocks *, + struct page **, int); +#endif static inline struct page * erofs_get_inline_page(struct inode *inode, diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index fc30025ef101..aed211cd5875 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -104,8 +104,6 @@ int erofs_register_workgroup(struct super_block *sb, return err; } -extern void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); - static void __erofs_workgroup_free(struct erofs_workgroup *grp) { atomic_long_dec(&erofs_global_shrink_cnt); -- cgit From 4b03f3f4ccb83c0d76ff61343a4267eac30f9e0c Mon Sep 17 00:00:00 2001 From: Sidong Yang Date: Tue, 8 Jan 2019 13:24:54 +0000 Subject: staging: erofs: Add identifier for function definition arguments Add identifier for function definition arguments in xattr_iter_handlers, this change clears the checkpatch.pl issue and make code more explicit. Signed-off-by: Sidong Yang Reviewed-by: Gao Xiang Reviewed-by: Chao Yu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/xattr.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/erofs/xattr.c b/drivers/staging/erofs/xattr.c index 80dca6a4adbe..59bc5641c4e7 100644 --- a/drivers/staging/erofs/xattr.c +++ b/drivers/staging/erofs/xattr.c @@ -117,10 +117,12 @@ static int init_inode_xattrs(struct inode *inode) * and need to be handled */ struct xattr_iter_handlers { - int (*entry)(struct xattr_iter *, struct erofs_xattr_entry *); - int (*name)(struct xattr_iter *, unsigned int, char *, unsigned int); - int (*alloc_buffer)(struct xattr_iter *, unsigned int); - void (*value)(struct xattr_iter *, unsigned int, char *, unsigned int); + int (*entry)(struct xattr_iter *_it, struct erofs_xattr_entry *entry); + int (*name)(struct xattr_iter *_it, unsigned int processed, char *buf, + unsigned int len); + int (*alloc_buffer)(struct xattr_iter *_it, unsigned int value_sz); + void (*value)(struct xattr_iter *_it, unsigned int processed, char *buf, + unsigned int len); }; static inline int xattr_iter_fixup(struct xattr_iter *it) -- cgit From 49ad8171e56c5ef5422837fd6fe5b6eb5091d27f Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Fri, 11 Jan 2019 13:57:05 -0600 Subject: iio: ti-ads124s08: Add DT binding documentation Adding binding documentation for Texas Instruments ADS124S08 and ADS124S06 ADC. S08 is a 12 channel ADC S06 is a 6 channel ADC Datesheet can be found here: http://www.ti.com/lit/gpn/ads124s08 Signed-off-by: Dan Murphy Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/adc/ti-ads124s08.txt | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/ti-ads124s08.txt diff --git a/Documentation/devicetree/bindings/iio/adc/ti-ads124s08.txt b/Documentation/devicetree/bindings/iio/adc/ti-ads124s08.txt new file mode 100644 index 000000000000..ecf807bb32f7 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti-ads124s08.txt @@ -0,0 +1,25 @@ +* Texas Instruments' ads124s08 and ads124s06 ADC chip + +Required properties: + - compatible : + "ti,ads124s08" + "ti,ads124s06" + - reg : spi chip select number for the device + +Recommended properties: + - spi-max-frequency : Definition as per + Documentation/devicetree/bindings/spi/spi-bus.txt + - spi-cpha : Definition as per + Documentation/devicetree/bindings/spi/spi-bus.txt + +Optional properties: + - reset-gpios : GPIO pin used to reset the device. + +Example: +adc@0 { + compatible = "ti,ads124s08"; + reg = <0>; + spi-max-frequency = <1000000>; + spi-cpha; + reset-gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; +}; -- cgit From e717f8c6dfec8f76be032fc2a7516de6e31a56a1 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Fri, 11 Jan 2019 13:57:06 -0600 Subject: iio: adc: Add the TI ads124s08 ADC code Introduce the TI ADS124S08 and the ADS124S06 ADC devices from TI. The ADS124S08 is the 12 channel ADC and the ADS124S06 is the 6 channel ADC device These devices share a common datasheet: http://www.ti.com/lit/gpn/ads124s08 Signed-off-by: Dan Murphy Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 10 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ti-ads124s08.c | 376 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 387 insertions(+) create mode 100644 drivers/iio/adc/ti-ads124s08.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index f3cc7a31bce5..f782d81137b3 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -935,6 +935,16 @@ config TI_ADS8688 This driver can also be built as a module. If so, the module will be called ti-ads8688. +config TI_ADS124S08 + tristate "Texas Instruments ADS124S08" + depends on SPI && OF + help + If you say yes here you get support for Texas Instruments ADS124S08 + and ADS124S06 ADC chips + + This driver can also be built as a module. If so, the module will be + called ti-ads124s08. + config TI_AM335X_ADC tristate "TI's AM335X ADC driver" depends on MFD_TI_AM335X_TSCADC && HAS_DMA diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index ea5031348052..2e7101e8a811 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o obj-$(CONFIG_TI_ADS7950) += ti-ads7950.o obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o +obj-$(CONFIG_TI_ADS124S08) += ti-ads124s08.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o obj-$(CONFIG_TI_TLC4541) += ti-tlc4541.o obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o diff --git a/drivers/iio/adc/ti-ads124s08.c b/drivers/iio/adc/ti-ads124s08.c new file mode 100644 index 000000000000..c2cf58908fc8 --- /dev/null +++ b/drivers/iio/adc/ti-ads124s08.c @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: GPL-2.0 +/* TI ADS124S0X chip family driver + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +/* Commands */ +#define ADS124S08_CMD_NOP 0x00 +#define ADS124S08_CMD_WAKEUP 0x02 +#define ADS124S08_CMD_PWRDWN 0x04 +#define ADS124S08_CMD_RESET 0x06 +#define ADS124S08_CMD_START 0x08 +#define ADS124S08_CMD_STOP 0x0a +#define ADS124S08_CMD_SYOCAL 0x16 +#define ADS124S08_CMD_SYGCAL 0x17 +#define ADS124S08_CMD_SFOCAL 0x19 +#define ADS124S08_CMD_RDATA 0x12 +#define ADS124S08_CMD_RREG 0x20 +#define ADS124S08_CMD_WREG 0x40 + +/* Registers */ +#define ADS124S08_ID_REG 0x00 +#define ADS124S08_STATUS 0x01 +#define ADS124S08_INPUT_MUX 0x02 +#define ADS124S08_PGA 0x03 +#define ADS124S08_DATA_RATE 0x04 +#define ADS124S08_REF 0x05 +#define ADS124S08_IDACMAG 0x06 +#define ADS124S08_IDACMUX 0x07 +#define ADS124S08_VBIAS 0x08 +#define ADS124S08_SYS 0x09 +#define ADS124S08_OFCAL0 0x0a +#define ADS124S08_OFCAL1 0x0b +#define ADS124S08_OFCAL2 0x0c +#define ADS124S08_FSCAL0 0x0d +#define ADS124S08_FSCAL1 0x0e +#define ADS124S08_FSCAL2 0x0f +#define ADS124S08_GPIODAT 0x10 +#define ADS124S08_GPIOCON 0x11 + +/* ADS124S0x common channels */ +#define ADS124S08_AIN0 0x00 +#define ADS124S08_AIN1 0x01 +#define ADS124S08_AIN2 0x02 +#define ADS124S08_AIN3 0x03 +#define ADS124S08_AIN4 0x04 +#define ADS124S08_AIN5 0x05 +#define ADS124S08_AINCOM 0x0c +/* ADS124S08 only channels */ +#define ADS124S08_AIN6 0x06 +#define ADS124S08_AIN7 0x07 +#define ADS124S08_AIN8 0x08 +#define ADS124S08_AIN9 0x09 +#define ADS124S08_AIN10 0x0a +#define ADS124S08_AIN11 0x0b +#define ADS124S08_MAX_CHANNELS 12 + +#define ADS124S08_POS_MUX_SHIFT 0x04 +#define ADS124S08_INT_REF 0x09 + +#define ADS124S08_START_REG_MASK 0x1f +#define ADS124S08_NUM_BYTES_MASK 0x1f + +#define ADS124S08_START_CONV 0x01 +#define ADS124S08_STOP_CONV 0x00 + +enum ads124s_id { + ADS124S08_ID, + ADS124S06_ID, +}; + +struct ads124s_chip_info { + const struct iio_chan_spec *channels; + unsigned int num_channels; +}; + +struct ads124s_private { + const struct ads124s_chip_info *chip_info; + struct gpio_desc *reset_gpio; + struct spi_device *spi; + struct mutex lock; + u8 data[5] ____cacheline_aligned; +}; + +#define ADS124S08_CHAN(index) \ +{ \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = index, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .scan_index = index, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 32, \ + .storagebits = 32, \ + }, \ +} + +static const struct iio_chan_spec ads124s06_channels[] = { + ADS124S08_CHAN(0), + ADS124S08_CHAN(1), + ADS124S08_CHAN(2), + ADS124S08_CHAN(3), + ADS124S08_CHAN(4), + ADS124S08_CHAN(5), +}; + +static const struct iio_chan_spec ads124s08_channels[] = { + ADS124S08_CHAN(0), + ADS124S08_CHAN(1), + ADS124S08_CHAN(2), + ADS124S08_CHAN(3), + ADS124S08_CHAN(4), + ADS124S08_CHAN(5), + ADS124S08_CHAN(6), + ADS124S08_CHAN(7), + ADS124S08_CHAN(8), + ADS124S08_CHAN(9), + ADS124S08_CHAN(10), + ADS124S08_CHAN(11), +}; + +static const struct ads124s_chip_info ads124s_chip_info_tbl[] = { + [ADS124S08_ID] = { + .channels = ads124s08_channels, + .num_channels = ARRAY_SIZE(ads124s08_channels), + }, + [ADS124S06_ID] = { + .channels = ads124s06_channels, + .num_channels = ARRAY_SIZE(ads124s06_channels), + }, +}; + +static int ads124s_write_cmd(struct iio_dev *indio_dev, u8 command) +{ + struct ads124s_private *priv = iio_priv(indio_dev); + + priv->data[0] = command; + + return spi_write(priv->spi, &priv->data[0], 1); +} + +static int ads124s_write_reg(struct iio_dev *indio_dev, u8 reg, u8 data) +{ + struct ads124s_private *priv = iio_priv(indio_dev); + + priv->data[0] = ADS124S08_CMD_WREG | reg; + priv->data[1] = 0x0; + priv->data[2] = data; + + return spi_write(priv->spi, &priv->data[0], 3); +} + +static int ads124s_reset(struct iio_dev *indio_dev) +{ + struct ads124s_private *priv = iio_priv(indio_dev); + + if (priv->reset_gpio) { + gpiod_set_value(priv->reset_gpio, 0); + udelay(200); + gpiod_set_value(priv->reset_gpio, 1); + } else { + return ads124s_write_cmd(indio_dev, ADS124S08_CMD_RESET); + } + + return 0; +}; + +static int ads124s_read(struct iio_dev *indio_dev, unsigned int chan) +{ + struct ads124s_private *priv = iio_priv(indio_dev); + int ret; + u32 tmp; + struct spi_transfer t[] = { + { + .tx_buf = &priv->data[0], + .len = 4, + .cs_change = 1, + }, { + .tx_buf = &priv->data[1], + .rx_buf = &priv->data[1], + .len = 4, + }, + }; + + priv->data[0] = ADS124S08_CMD_RDATA; + memset(&priv->data[1], ADS124S08_CMD_NOP, sizeof(priv->data)); + + ret = spi_sync_transfer(priv->spi, t, ARRAY_SIZE(t)); + if (ret < 0) + return ret; + + tmp = priv->data[2] << 16 | priv->data[3] << 8 | priv->data[4]; + + return tmp; +} + +static int ads124s_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long m) +{ + struct ads124s_private *priv = iio_priv(indio_dev); + int ret; + + mutex_lock(&priv->lock); + switch (m) { + case IIO_CHAN_INFO_RAW: + ret = ads124s_write_reg(indio_dev, ADS124S08_INPUT_MUX, + chan->channel); + if (ret) { + dev_err(&priv->spi->dev, "Set ADC CH failed\n"); + goto out; + } + + ret = ads124s_write_cmd(indio_dev, ADS124S08_START_CONV); + if (ret) { + dev_err(&priv->spi->dev, "Start converions failed\n"); + goto out; + } + + ret = ads124s_read(indio_dev, chan->channel); + if (ret < 0) { + dev_err(&priv->spi->dev, "Read ADC failed\n"); + goto out; + } + + *val = ret; + + ret = ads124s_write_cmd(indio_dev, ADS124S08_STOP_CONV); + if (ret) { + dev_err(&priv->spi->dev, "Stop converions failed\n"); + goto out; + } + + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + break; + } +out: + mutex_unlock(&priv->lock); + return ret; +} + +static const struct iio_info ads124s_info = { + .read_raw = &ads124s_read_raw, +}; + +static irqreturn_t ads124s_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ads124s_private *priv = iio_priv(indio_dev); + u32 buffer[ADS124S08_MAX_CHANNELS + sizeof(s64)/sizeof(u16)]; + int scan_index, j = 0; + int ret; + + for_each_set_bit(scan_index, indio_dev->active_scan_mask, + indio_dev->masklength) { + ret = ads124s_write_reg(indio_dev, ADS124S08_INPUT_MUX, + scan_index); + if (ret) + dev_err(&priv->spi->dev, "Set ADC CH failed\n"); + + ret = ads124s_write_cmd(indio_dev, ADS124S08_START_CONV); + if (ret) + dev_err(&priv->spi->dev, "Start ADC converions failed\n"); + + buffer[j] = ads124s_read(indio_dev, scan_index); + ret = ads124s_write_cmd(indio_dev, ADS124S08_STOP_CONV); + if (ret) + dev_err(&priv->spi->dev, "Stop ADC converions failed\n"); + + j++; + } + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, + pf->timestamp); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int ads124s_probe(struct spi_device *spi) +{ + struct ads124s_private *ads124s_priv; + struct iio_dev *indio_dev; + const struct spi_device_id *spi_id = spi_get_device_id(spi); + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*ads124s_priv)); + if (indio_dev == NULL) + return -ENOMEM; + + ads124s_priv = iio_priv(indio_dev); + + ads124s_priv->reset_gpio = devm_gpiod_get_optional(&spi->dev, + "reset", GPIOD_OUT_LOW); + if (IS_ERR(ads124s_priv->reset_gpio)) + dev_info(&spi->dev, "Reset GPIO not defined\n"); + + ads124s_priv->chip_info = &ads124s_chip_info_tbl[spi_id->driver_data]; + + spi_set_drvdata(spi, indio_dev); + + ads124s_priv->spi = spi; + + indio_dev->name = spi_id->name; + indio_dev->dev.parent = &spi->dev; + indio_dev->dev.of_node = spi->dev.of_node; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ads124s_priv->chip_info->channels; + indio_dev->num_channels = ads124s_priv->chip_info->num_channels; + indio_dev->info = &ads124s_info; + + mutex_init(&ads124s_priv->lock); + + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, + ads124s_trigger_handler, NULL); + if (ret) { + dev_err(&spi->dev, "iio triggered buffer setup failed\n"); + return ret; + } + + ads124s_reset(indio_dev); + + return devm_iio_device_register(&spi->dev, indio_dev); +} + +static const struct spi_device_id ads124s_id[] = { + { "ads124s06", ADS124S06_ID }, + { "ads124s08", ADS124S08_ID }, + { } +}; +MODULE_DEVICE_TABLE(spi, ads124s_id); + +static const struct of_device_id ads124s_of_table[] = { + { .compatible = "ti,ads124s06" }, + { .compatible = "ti,ads124s08" }, + { }, +}; +MODULE_DEVICE_TABLE(of, ads124s_of_table); + +static struct spi_driver ads124s_driver = { + .driver = { + .name = "ads124s08", + .of_match_table = ads124s_of_table, + }, + .probe = ads124s_probe, + .id_table = ads124s_id, +}; +module_spi_driver(ads124s_driver); + +MODULE_AUTHOR("Dan Murphy "); +MODULE_DESCRIPTION("TI TI_ADS12S0X ADC"); +MODULE_LICENSE("GPL v2"); -- cgit From 192778fb969c2b9bc33d559b9c7aecdd1498c1ba Mon Sep 17 00:00:00 2001 From: Mircea Caprioru Date: Wed, 9 Jan 2019 11:14:16 +0200 Subject: iio: dac: ad5686: Add support for AD5674R/AD5679R The AD5674R/AD5679R are low power, 16-channel, 12-/16-bit buffered voltage output digital-to-analog converters (DACs). They include a 2.5 V internal reference (enabled by default). These devices are very similar to AD5684R/AD5686R, except that they have 16 channels. Signed-off-by: Mircea Caprioru Signed-off-by: Jonathan Cameron --- drivers/iio/dac/Kconfig | 6 +++--- drivers/iio/dac/ad5686-spi.c | 7 +++++-- drivers/iio/dac/ad5686.c | 42 ++++++++++++++++++++++++++++++++++++++++-- drivers/iio/dac/ad5686.h | 2 ++ 4 files changed, 50 insertions(+), 7 deletions(-) diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index 851b61eaf3da..f28daf67db6a 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -148,9 +148,9 @@ config AD5686_SPI depends on SPI select AD5686 help - Say yes here to build support for Analog Devices AD5672R, AD5676, - AD5676R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, AD5686R. - Voltage Output Digital to Analog Converter. + Say yes here to build support for Analog Devices AD5672R, AD5674R, + AD5676, AD5676R, AD5679R, AD5684, AD5684R, AD5684R, AD5685R, AD5686, + AD5686R Voltage Output Digital to Analog Converter. To compile this driver as a module, choose M here: the module will be called ad5686. diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c index 665fa6bd9ced..4d857c8da2d2 100644 --- a/drivers/iio/dac/ad5686-spi.c +++ b/drivers/iio/dac/ad5686-spi.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * AD5672R, AD5676, AD5676R, AD5681R, AD5682R, AD5683, AD5683R, - * AD5684, AD5684R, AD5685R, AD5686, AD5686R + * AD5672R, AD5674R, AD5676, AD5676R, AD5679R, + * AD5681R, AD5682R, AD5683, AD5683R, AD5684, + * AD5684R, AD5685R, AD5686, AD5686R * Digital to analog converters driver * * Copyright 2018 Analog Devices Inc. @@ -102,8 +103,10 @@ static int ad5686_spi_remove(struct spi_device *spi) static const struct spi_device_id ad5686_spi_id[] = { {"ad5310r", ID_AD5310R}, {"ad5672r", ID_AD5672R}, + {"ad5674r", ID_AD5674R}, {"ad5676", ID_AD5676}, {"ad5676r", ID_AD5676R}, + {"ad5679r", ID_AD5679R}, {"ad5681r", ID_AD5681R}, {"ad5682r", ID_AD5682R}, {"ad5683", ID_AD5683}, diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index a332b93ca2c4..6dd2759b9092 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -71,7 +71,7 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, int ret; struct ad5686_state *st = iio_priv(indio_dev); unsigned int val, ref_bit_msk; - u8 shift; + u8 shift, address = 0; ret = strtobool(buf, &readin); if (ret) @@ -94,6 +94,9 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, case AD5686_REGMAP: shift = 0; ref_bit_msk = 0; + /* AD5674R/AD5679R have 16 channels and 2 powerdown registers */ + if (chan->channel > 0x7) + address = 0x8; break; case AD5693_REGMAP: shift = 13; @@ -107,7 +110,8 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev, if (!st->use_internal_vref) val |= ref_bit_msk; - ret = st->write(st, AD5686_CMD_POWERDOWN_DAC, 0, val); + ret = st->write(st, AD5686_CMD_POWERDOWN_DAC, + address, val >> (address * 2)); return ret ? ret : len; } @@ -226,10 +230,32 @@ static struct iio_chan_spec name[] = { \ AD5868_CHANNEL(7, 7, bits, _shift), \ } +#define DECLARE_AD5679_CHANNELS(name, bits, _shift) \ +static struct iio_chan_spec name[] = { \ + AD5868_CHANNEL(0, 0, bits, _shift), \ + AD5868_CHANNEL(1, 1, bits, _shift), \ + AD5868_CHANNEL(2, 2, bits, _shift), \ + AD5868_CHANNEL(3, 3, bits, _shift), \ + AD5868_CHANNEL(4, 4, bits, _shift), \ + AD5868_CHANNEL(5, 5, bits, _shift), \ + AD5868_CHANNEL(6, 6, bits, _shift), \ + AD5868_CHANNEL(7, 7, bits, _shift), \ + AD5868_CHANNEL(8, 8, bits, _shift), \ + AD5868_CHANNEL(9, 9, bits, _shift), \ + AD5868_CHANNEL(10, 10, bits, _shift), \ + AD5868_CHANNEL(11, 11, bits, _shift), \ + AD5868_CHANNEL(12, 12, bits, _shift), \ + AD5868_CHANNEL(13, 13, bits, _shift), \ + AD5868_CHANNEL(14, 14, bits, _shift), \ + AD5868_CHANNEL(15, 15, bits, _shift), \ +} + DECLARE_AD5693_CHANNELS(ad5310r_channels, 10, 2); DECLARE_AD5693_CHANNELS(ad5311r_channels, 10, 6); DECLARE_AD5676_CHANNELS(ad5672_channels, 12, 4); +DECLARE_AD5679_CHANNELS(ad5674r_channels, 12, 4); DECLARE_AD5676_CHANNELS(ad5676_channels, 16, 0); +DECLARE_AD5679_CHANNELS(ad5679r_channels, 16, 0); DECLARE_AD5686_CHANNELS(ad5684_channels, 12, 4); DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2); DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0); @@ -262,6 +288,12 @@ static const struct ad5686_chip_info ad5686_chip_info_tbl[] = { .num_channels = 8, .regmap_type = AD5686_REGMAP, }, + [ID_AD5674R] = { + .channels = ad5674r_channels, + .int_vref_mv = 2500, + .num_channels = 16, + .regmap_type = AD5686_REGMAP, + }, [ID_AD5675R] = { .channels = ad5676_channels, .int_vref_mv = 2500, @@ -279,6 +311,12 @@ static const struct ad5686_chip_info ad5686_chip_info_tbl[] = { .num_channels = 8, .regmap_type = AD5686_REGMAP, }, + [ID_AD5679R] = { + .channels = ad5679r_channels, + .int_vref_mv = 2500, + .num_channels = 16, + .regmap_type = AD5686_REGMAP, + }, [ID_AD5681R] = { .channels = ad5691r_channels, .int_vref_mv = 2500, diff --git a/drivers/iio/dac/ad5686.h b/drivers/iio/dac/ad5686.h index 19f6917d4738..4c3e171ce0cc 100644 --- a/drivers/iio/dac/ad5686.h +++ b/drivers/iio/dac/ad5686.h @@ -54,9 +54,11 @@ enum ad5686_supported_device_ids { ID_AD5311R, ID_AD5671R, ID_AD5672R, + ID_AD5674R, ID_AD5675R, ID_AD5676, ID_AD5676R, + ID_AD5679R, ID_AD5681R, ID_AD5682R, ID_AD5683, -- cgit From 1dca9bdec6cbec80de7ddd0f2df05886c1fa82bc Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 8 Jan 2019 09:16:04 +0000 Subject: iio: magnetometer: mag3110: add vdd/vddio regulator operation support The magnetometer's power supplies could be controllable on some platforms, such as i.MX6Q-SABRESD board, the mag3110's power supplies are controlled by a GPIO fixed regulator, need to make sure the regulators are enabled before any communication with mag3110, this patch adds vdd/vddio regulator operation support. Signed-off-by: Anson Huang Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/mag3110.c | 94 ++++++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 8 deletions(-) diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index f063355480ba..dd990cdb04a8 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c @@ -20,6 +20,7 @@ #include #include #include +#include #define MAG3110_STATUS 0x00 #define MAG3110_OUT_X 0x01 /* MSB first */ @@ -56,6 +57,8 @@ struct mag3110_data { struct mutex lock; u8 ctrl_reg1; int sleep_val; + struct regulator *vdd_reg; + struct regulator *vddio_reg; }; static int mag3110_request(struct mag3110_data *data) @@ -469,17 +472,50 @@ static int mag3110_probe(struct i2c_client *client, struct iio_dev *indio_dev; int ret; - ret = i2c_smbus_read_byte_data(client, MAG3110_WHO_AM_I); - if (ret < 0) - return ret; - if (ret != MAG3110_DEVICE_ID) - return -ENODEV; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); + + data->vdd_reg = devm_regulator_get(&client->dev, "vdd"); + if (IS_ERR(data->vdd_reg)) { + if (PTR_ERR(data->vdd_reg) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_err(&client->dev, "failed to get VDD regulator!\n"); + return PTR_ERR(data->vdd_reg); + } + + data->vddio_reg = devm_regulator_get(&client->dev, "vddio"); + if (IS_ERR(data->vddio_reg)) { + if (PTR_ERR(data->vddio_reg) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_err(&client->dev, "failed to get VDDIO regulator!\n"); + return PTR_ERR(data->vddio_reg); + } + + ret = regulator_enable(data->vdd_reg); + if (ret) { + dev_err(&client->dev, "failed to enable VDD regulator!\n"); + return ret; + } + + ret = regulator_enable(data->vddio_reg); + if (ret) { + dev_err(&client->dev, "failed to enable VDDIO regulator!\n"); + goto disable_regulator_vdd; + } + + ret = i2c_smbus_read_byte_data(client, MAG3110_WHO_AM_I); + if (ret < 0) + goto disable_regulators; + if (ret != MAG3110_DEVICE_ID) { + ret = -ENODEV; + goto disable_regulators; + } + data->client = client; mutex_init(&data->lock); @@ -499,7 +535,7 @@ static int mag3110_probe(struct i2c_client *client, ret = mag3110_change_config(data, MAG3110_CTRL_REG1, data->ctrl_reg1); if (ret < 0) - return ret; + goto disable_regulators; ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG2, MAG3110_CTRL_AUTO_MRST_EN); @@ -520,16 +556,24 @@ buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); standby_on_error: mag3110_standby(iio_priv(indio_dev)); +disable_regulators: + regulator_disable(data->vddio_reg); +disable_regulator_vdd: + regulator_disable(data->vdd_reg); + return ret; } static int mag3110_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct mag3110_data *data = iio_priv(indio_dev); iio_device_unregister(indio_dev); iio_triggered_buffer_cleanup(indio_dev); mag3110_standby(iio_priv(indio_dev)); + regulator_disable(data->vddio_reg); + regulator_disable(data->vdd_reg); return 0; } @@ -537,14 +581,48 @@ static int mag3110_remove(struct i2c_client *client) #ifdef CONFIG_PM_SLEEP static int mag3110_suspend(struct device *dev) { - return mag3110_standby(iio_priv(i2c_get_clientdata( + struct mag3110_data *data = iio_priv(i2c_get_clientdata( + to_i2c_client(dev))); + int ret; + + ret = mag3110_standby(iio_priv(i2c_get_clientdata( to_i2c_client(dev)))); + if (ret) + return ret; + + ret = regulator_disable(data->vddio_reg); + if (ret) { + dev_err(dev, "failed to disable VDDIO regulator\n"); + return ret; + } + + ret = regulator_disable(data->vdd_reg); + if (ret) { + dev_err(dev, "failed to disable VDD regulator\n"); + return ret; + } + + return 0; } static int mag3110_resume(struct device *dev) { struct mag3110_data *data = iio_priv(i2c_get_clientdata( to_i2c_client(dev))); + int ret; + + ret = regulator_enable(data->vdd_reg); + if (ret) { + dev_err(dev, "failed to enable VDD regulator\n"); + return ret; + } + + ret = regulator_enable(data->vddio_reg); + if (ret) { + dev_err(dev, "failed to enable VDDIO regulator\n"); + regulator_disable(data->vdd_reg); + return ret; + } return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1, data->ctrl_reg1); -- cgit From 1a02d1239389a9ef81daf4913ce60e9f71f8a61f Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 8 Jan 2019 09:09:39 +0000 Subject: iio: light: isl29018: add vcc regulator operation support The light sensor's power supply could be controllable by regulator on some platforms, such as i.MX6Q-SABRESD board, the light sensor isl29023's power supply is controlled by a GPIO fixed regulator, need to make sure the regulator is enabled before any operation of sensor, this patch adds vcc regulator operation support. Signed-off-by: Anson Huang Signed-off-by: Jonathan Cameron --- drivers/iio/light/isl29018.c | 46 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c index b45400f8fef4..846df4dce48c 100644 --- a/drivers/iio/light/isl29018.c +++ b/drivers/iio/light/isl29018.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +96,7 @@ struct isl29018_chip { struct isl29018_scale scale; int prox_scheme; bool suspended; + struct regulator *vcc_reg; }; static int isl29018_set_integration_time(struct isl29018_chip *chip, @@ -708,6 +710,16 @@ static const char *isl29018_match_acpi_device(struct device *dev, int *data) return dev_name(dev); } +static void isl29018_disable_regulator_action(void *_data) +{ + struct isl29018_chip *chip = _data; + int err; + + err = regulator_disable(chip->vcc_reg); + if (err) + pr_err("failed to disable isl29018's VCC regulator!\n"); +} + static int isl29018_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -742,6 +754,27 @@ static int isl29018_probe(struct i2c_client *client, chip->scale = isl29018_scales[chip->int_time][0]; chip->suspended = false; + chip->vcc_reg = devm_regulator_get(&client->dev, "vcc"); + if (IS_ERR(chip->vcc_reg)) { + err = PTR_ERR(chip->vcc_reg); + if (err != -EPROBE_DEFER) + dev_err(&client->dev, "failed to get VCC regulator!\n"); + return err; + } + + err = regulator_enable(chip->vcc_reg); + if (err) { + dev_err(&client->dev, "failed to enable VCC regulator!\n"); + return err; + } + + err = devm_add_action_or_reset(&client->dev, isl29018_disable_regulator_action, + chip); + if (err) { + dev_err(&client->dev, "failed to setup regulator cleanup action!\n"); + return err; + } + chip->regmap = devm_regmap_init_i2c(client, isl29018_chip_info_tbl[dev_id].regmap_cfg); if (IS_ERR(chip->regmap)) { @@ -768,6 +801,7 @@ static int isl29018_probe(struct i2c_client *client, static int isl29018_suspend(struct device *dev) { struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev)); + int ret; mutex_lock(&chip->lock); @@ -777,10 +811,13 @@ static int isl29018_suspend(struct device *dev) * So we do not have much to do here. */ chip->suspended = true; + ret = regulator_disable(chip->vcc_reg); + if (ret) + dev_err(dev, "failed to disable VCC regulator\n"); mutex_unlock(&chip->lock); - return 0; + return ret; } static int isl29018_resume(struct device *dev) @@ -790,6 +827,13 @@ static int isl29018_resume(struct device *dev) mutex_lock(&chip->lock); + err = regulator_enable(chip->vcc_reg); + if (err) { + dev_err(dev, "failed to enable VCC regulator\n"); + mutex_unlock(&chip->lock); + return err; + } + err = isl29018_chip_init(chip); if (!err) chip->suspended = false; -- cgit From a7b4f316af857915e27633e48600c146b4978522 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 8 Jan 2019 09:14:01 +0000 Subject: dt-bindings: iio: accel: mma8452: add power supplies property The accelerometer's power supplies could be controllable on some platforms, add property "vdd/vddio" power supply to let device tree to pass phandles to the regulators to driver. Signed-off-by: Anson Huang Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/accel/mma8452.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/accel/mma8452.txt b/Documentation/devicetree/bindings/iio/accel/mma8452.txt index 2100e9af379c..e132394375a1 100644 --- a/Documentation/devicetree/bindings/iio/accel/mma8452.txt +++ b/Documentation/devicetree/bindings/iio/accel/mma8452.txt @@ -20,6 +20,10 @@ Optional properties: - interrupt-names: should contain "INT1" and/or "INT2", the accelerometer's interrupt line in use. + - vdd-supply: phandle to the regulator that provides vdd power to the accelerometer. + + - vddio-supply: phandle to the regulator that provides vddio power to the accelerometer. + Example: mma8453fc@1d { -- cgit From f6ff49b8a3b6f774777a21a5a0725d98dee5f2d1 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Tue, 8 Jan 2019 09:14:06 +0000 Subject: iio: accell: mma8452: add vdd/vddio regulator operation support The accelerometer's power supply could be controllable on some platforms, such as i.MX6Q-SABRESD board, the mma8451's power supplies are controlled by a GPIO fixed regulator, need to make sure the regulators are enabled before any communication with mma8451, this patch adds vdd/vddio regulator operation support. Signed-off-by: Anson Huang Acked-by: Martin Kepplinger Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 105 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 22 deletions(-) diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 421a0a8a1379..302781126bc6 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -31,6 +31,7 @@ #include #include #include +#include #define MMA8452_STATUS 0x00 #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) @@ -107,6 +108,8 @@ struct mma8452_data { u8 data_cfg; const struct mma_chip_info *chip_info; int sleep_val; + struct regulator *vdd_reg; + struct regulator *vddio_reg; }; /** @@ -1534,9 +1537,39 @@ static int mma8452_probe(struct i2c_client *client, mutex_init(&data->lock); data->chip_info = match->data; + data->vdd_reg = devm_regulator_get(&client->dev, "vdd"); + if (IS_ERR(data->vdd_reg)) { + if (PTR_ERR(data->vdd_reg) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_err(&client->dev, "failed to get VDD regulator!\n"); + return PTR_ERR(data->vdd_reg); + } + + data->vddio_reg = devm_regulator_get(&client->dev, "vddio"); + if (IS_ERR(data->vddio_reg)) { + if (PTR_ERR(data->vddio_reg) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_err(&client->dev, "failed to get VDDIO regulator!\n"); + return PTR_ERR(data->vddio_reg); + } + + ret = regulator_enable(data->vdd_reg); + if (ret) { + dev_err(&client->dev, "failed to enable VDD regulator!\n"); + return ret; + } + + ret = regulator_enable(data->vddio_reg); + if (ret) { + dev_err(&client->dev, "failed to enable VDDIO regulator!\n"); + goto disable_regulator_vdd; + } + ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I); if (ret < 0) - return ret; + goto disable_regulators; switch (ret) { case MMA8451_DEVICE_ID: @@ -1549,7 +1582,8 @@ static int mma8452_probe(struct i2c_client *client, break; /* else: fall through */ default: - return -ENODEV; + ret = -ENODEV; + goto disable_regulators; } dev_info(&client->dev, "registering %s accelerometer; ID 0x%x\n", @@ -1566,13 +1600,13 @@ static int mma8452_probe(struct i2c_client *client, ret = mma8452_reset(client); if (ret < 0) - return ret; + goto disable_regulators; data->data_cfg = MMA8452_DATA_CFG_FS_2G; ret = i2c_smbus_write_byte_data(client, MMA8452_DATA_CFG, data->data_cfg); if (ret < 0) - return ret; + goto disable_regulators; /* * By default set transient threshold to max to avoid events if @@ -1581,7 +1615,7 @@ static int mma8452_probe(struct i2c_client *client, ret = i2c_smbus_write_byte_data(client, MMA8452_TRANSIENT_THS, MMA8452_TRANSIENT_THS_MASK); if (ret < 0) - return ret; + goto disable_regulators; if (client->irq) { int irq2; @@ -1595,7 +1629,7 @@ static int mma8452_probe(struct i2c_client *client, MMA8452_CTRL_REG5, data->chip_info->all_events); if (ret < 0) - return ret; + goto disable_regulators; dev_dbg(&client->dev, "using interrupt line INT1\n"); } @@ -1604,11 +1638,11 @@ static int mma8452_probe(struct i2c_client *client, MMA8452_CTRL_REG4, data->chip_info->enabled_events); if (ret < 0) - return ret; + goto disable_regulators; ret = mma8452_trigger_setup(indio_dev); if (ret < 0) - return ret; + goto disable_regulators; } data->ctrl_reg1 = MMA8452_CTRL_ACTIVE | @@ -1661,12 +1695,19 @@ buffer_cleanup: trigger_cleanup: mma8452_trigger_cleanup(indio_dev); +disable_regulators: + regulator_disable(data->vddio_reg); + +disable_regulator_vdd: + regulator_disable(data->vdd_reg); + return ret; } static int mma8452_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct mma8452_data *data = iio_priv(indio_dev); iio_device_unregister(indio_dev); @@ -1678,6 +1719,9 @@ static int mma8452_remove(struct i2c_client *client) mma8452_trigger_cleanup(indio_dev); mma8452_standby(iio_priv(indio_dev)); + regulator_disable(data->vddio_reg); + regulator_disable(data->vdd_reg); + return 0; } @@ -1696,6 +1740,18 @@ static int mma8452_runtime_suspend(struct device *dev) return -EAGAIN; } + ret = regulator_disable(data->vddio_reg); + if (ret) { + dev_err(dev, "failed to disable VDDIO regulator\n"); + return ret; + } + + ret = regulator_disable(data->vdd_reg); + if (ret) { + dev_err(dev, "failed to disable VDD regulator\n"); + return ret; + } + return 0; } @@ -1705,9 +1761,22 @@ static int mma8452_runtime_resume(struct device *dev) struct mma8452_data *data = iio_priv(indio_dev); int ret, sleep_val; + ret = regulator_enable(data->vdd_reg); + if (ret) { + dev_err(dev, "failed to enable VDD regulator\n"); + return ret; + } + + ret = regulator_enable(data->vddio_reg); + if (ret) { + dev_err(dev, "failed to enable VDDIO regulator\n"); + regulator_disable(data->vdd_reg); + return ret; + } + ret = mma8452_active(data); if (ret < 0) - return ret; + goto runtime_resume_failed; ret = mma8452_get_odr_index(data); sleep_val = 1000 / mma8452_samp_freq[ret][0]; @@ -1717,25 +1786,17 @@ static int mma8452_runtime_resume(struct device *dev) msleep_interruptible(sleep_val); return 0; -} -#endif -#ifdef CONFIG_PM_SLEEP -static int mma8452_suspend(struct device *dev) -{ - return mma8452_standby(iio_priv(i2c_get_clientdata( - to_i2c_client(dev)))); -} +runtime_resume_failed: + regulator_disable(data->vddio_reg); + regulator_disable(data->vdd_reg); -static int mma8452_resume(struct device *dev) -{ - return mma8452_active(iio_priv(i2c_get_clientdata( - to_i2c_client(dev)))); + return ret; } #endif static const struct dev_pm_ops mma8452_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(mma8452_suspend, mma8452_resume) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) SET_RUNTIME_PM_OPS(mma8452_runtime_suspend, mma8452_runtime_resume, NULL) }; -- cgit From fdb0536469cbc959a044fe61f07e6798d0d08445 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Tue, 15 Jan 2019 01:39:29 +0800 Subject: staging: erofs: add document This documents key feature, usage, and on-disk design of erofs. Reviewed-by: Chao Yu Cc: Signed-off-by: Gao Xiang Signed-off-by: Greg Kroah-Hartman --- .../erofs/Documentation/filesystems/erofs.txt | 206 +++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 drivers/staging/erofs/Documentation/filesystems/erofs.txt diff --git a/drivers/staging/erofs/Documentation/filesystems/erofs.txt b/drivers/staging/erofs/Documentation/filesystems/erofs.txt new file mode 100644 index 000000000000..803988d74c21 --- /dev/null +++ b/drivers/staging/erofs/Documentation/filesystems/erofs.txt @@ -0,0 +1,206 @@ +Overview +======== + +EROFS file-system stands for Enhanced Read-Only File System. Different +from other read-only file systems, it aims to be designed for flexibility, +scalability, but be kept simple and high performance. + +It is designed as a better filesystem solution for the following scenarios: + - read-only storage media or + + - part of a fully trusted read-only solution, which means it needs to be + immutable and bit-for-bit identical to the official golden image for + their releases due to security and other considerations and + + - hope to save some extra storage space with guaranteed end-to-end performance + by using reduced metadata and transparent file compression, especially + for those embedded devices with limited memory (ex, smartphone); + +Here is the main features of EROFS: + - Little endian on-disk design; + + - Currently 4KB block size (nobh) and therefore maximum 16TB address space; + + - Metadata & data could be mixed by design; + + - 2 inode versions for different requirements: + v1 v2 + Inode metadata size: 32 bytes 64 bytes + Max file size: 4 GB 16 EB (also limited by max. vol size) + Max uids/gids: 65536 4294967296 + File creation time: no yes (64 + 32-bit timestamp) + Max hardlinks: 65536 4294967296 + Metadata reserved: 4 bytes 14 bytes + + - Support extended attributes (xattrs) as an option; + + - Support xattr inline and tail-end data inline for all files; + + - Support transparent file compression as an option: + LZ4 algorithm with 4 KB fixed-output compression for high performance; + +The following git tree provides the file system user-space tools under +development (ex, formatting tool mkfs.erofs): +>> git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git + +Bugs and patches are welcome, please kindly help us and send to the following +linux-erofs mailing list: +>> linux-erofs mailing list + +Note that EROFS is still working in progress as a Linux staging driver, +Cc the staging mailing list as well is highly recommended: +>> Linux Driver Project Developer List + +Mount options +============= + +fault_injection=%d Enable fault injection in all supported types with + specified injection rate. Supported injection type: + Type_Name Type_Value + FAULT_KMALLOC 0x000000001 +(no)user_xattr Setup Extended User Attributes. Note: xattr is enabled + by default if CONFIG_EROFS_FS_XATTR is selected. +(no)acl Setup POSIX Access Control List. Note: acl is enabled + by default if CONFIG_EROFS_FS_POSIX_ACL is selected. + +On-disk details +=============== + +Summary +------- +Different from other read-only file systems, an EROFS volume is designed +to be as simple as possible: + + |-> aligned with the block size + ____________________________________________________________ + | |SB| | ... | Metadata | ... | Data | Metadata | ... | Data | + |_|__|_|_____|__________|_____|______|__________|_____|______| + 0 +1K + +All data areas should be aligned with the block size, but metadata areas +may not. All metadatas can be now observed in two different spaces (views): + 1. Inode metadata space + Each valid inode should be aligned with an inode slot, which is a fixed + value (32 bytes) and designed to be kept in line with v1 inode size. + + Each inode can be directly found with the following formula: + inode offset = meta_blkaddr * block_size + 32 * nid + + |-> aligned with 8B + |-> followed closely + + meta_blkaddr blocks |-> another slot + _____________________________________________________________________ + | ... | inode | xattrs | extents | data inline | ... | inode ... + |________|_______|(optional)|(optional)|__(optional)_|_____|__________ + |-> aligned with the inode slot size + . . + . . + . . + . . + . . + . . + .____________________________________________________|-> aligned with 4B + | xattr_ibody_header | shared xattrs | inline xattrs | + |____________________|_______________|_______________| + |-> 12 bytes <-|->x * 4 bytes<-| . + . . . + . . . + . . . + ._______________________________.______________________. + | id | id | id | id | ... | id | ent | ... | ent| ... | + |____|____|____|____|______|____|_____|_____|____|_____| + |-> aligned with 4B + |-> aligned with 4B + + Inode could be 32 or 64 bytes, which can be distinguished from a common + field which all inode versions have -- i_advise: + + __________________ __________________ + | i_advise | | i_advise | + |__________________| |__________________| + | ... | | ... | + | | | | + |__________________| 32 bytes | | + | | + |__________________| 64 bytes + + Xattrs, extents, data inline are followed by the corresponding inode with + proper alignes, and they could be optional for different data mappings, + _currently_ there are totally 3 valid data mappings supported: + + 1) flat file data without data inline (no extent); + 2) fixed-output size data compression (must have extents); + 3) flat file data with tail-end data inline (no extent); + + The size of the optional xattrs is indicated by i_xattr_count in inode + header. Large xattrs or xattrs shared by many different files can be + stored in shared xattrs metadata rather than inlined right after inode. + + 2. Shared xattrs metadata space + Shared xattrs space is similar to the above inode space, started with + a specific block indicated by xattr_blkaddr, organized one by one with + proper align. + + Each share xattr can also be directly found by the following formula: + xattr offset = xattr_blkaddr * block_size + 4 * xattr_id + + |-> aligned by 4 bytes + + xattr_blkaddr blocks |-> aligned with 4 bytes + _________________________________________________________________________ + | ... | xattr_entry | xattr data | ... | xattr_entry | xattr data ... + |________|_____________|_____________|_____|______________|_______________ + +Directories +----------- +All directories are now organized in a compact on-disk format. Note that +each directory block is divided into index and name areas in order to support +random file lookup, and all directory entries are _strictly_ recorded in +alphabetical order in order to support improved prefix binary search +algorithm (could refer to the related source code). + + ___________________________ + / | + / ______________|________________ + / / | nameoff1 | nameoffN-1 + ____________.______________._______________v________________v__________ +| dirent | dirent | ... | dirent | filename | filename | ... | filename | +|___.0___|____1___|_____|___N-1__|____0_____|____1_____|_____|___N-1____| + \ ^ + \ | * could have + \ | trailing '\0' + \________________________| nameoff0 + + Directory block + +Note that apart from the offset of the first filename, nameoff0 also indicates +the total number of directory entries in this block since it is no need to +introduce another on-disk field at all. + +Compression +----------- +Currently, EROFS supports 4KB fixed-output clustersize transparent file +compression, as illustrated below: + + |---- Variant-Length Extent ----|-------- VLE --------|----- VLE ----- + clusterofs clusterofs clusterofs + | | | logical data +_________v_______________________________v_____________________v_______________ +... | . | | . | | . | ... +____|____.________|_____________|________.____|_____________|__.__________|____ + |-> cluster <-|-> cluster <-|-> cluster <-|-> cluster <-|-> cluster <-| + size size size size size + . . . . + . . . . + . . . . + _______._____________._____________._____________._____________________ + ... | | | | ... physical data + _______|_____________|_____________|_____________|_____________________ + |-> cluster <-|-> cluster <-|-> cluster <-| + size size size + +Currently each on-disk physical cluster can contain 4KB (un)compressed data +at most. For each logical cluster, there is a corresponding on-disk index to +describe its cluster type, physical cluster address, etc. + +See "struct z_erofs_vle_decompressed_index" in erofs_fs.h for more details. + -- cgit From 7077fffcb0b0b65dc75e341306aeef4d0e7f2ec6 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Mon, 14 Jan 2019 19:40:23 +0800 Subject: staging: erofs: fix fast symlink w/o xattr when fs xattr is on Currently, this will hit a BUG_ON for these symlinks as follows: - kernel message ------------[ cut here ]------------ kernel BUG at drivers/staging/erofs/xattr.c:59! SMP PTI CPU: 1 PID: 1170 Comm: getllxattr Not tainted 4.20.0-rc6+ #92 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-2.fc27 04/01/2014 RIP: 0010:init_inode_xattrs+0x22b/0x270 Code: 48 0f 45 ea f0 ff 4d 34 74 0d 41 83 4c 24 e0 01 31 c0 e9 00 fe ff ff 48 89 ef e8 e0 31 9e ff eb e9 89 e8 e9 ef fd ff ff 0f 0$ <0f> 0b 48 89 ef e8 fb f6 9c ff 48 8b 45 08 a8 01 75 24 f0 ff 4d 34 RSP: 0018:ffffa03ac026bdf8 EFLAGS: 00010246 ------------[ cut here ]------------ ... Call Trace: erofs_listxattr+0x30/0x2c0 ? selinux_inode_listxattr+0x5a/0x80 ? kmem_cache_alloc+0x33/0x170 ? security_inode_listxattr+0x27/0x40 listxattr+0xaf/0xc0 path_listxattr+0x5a/0xa0 do_syscall_64+0x43/0xf0 entry_SYSCALL_64_after_hwframe+0x44/0xa9 ... ---[ end trace 3c24b49408dc0c72 ]--- Fix it by checking ->xattr_isize in init_inode_xattrs(), and it also fixes improper return value -ENOTSUPP (it should be -ENODATA if xattr is enabled) for those inodes. Fixes: b17500a0fdba ("staging: erofs: introduce xattr & acl support") Cc: # 4.19+ Reported-by: Li Guifu Tested-by: Li Guifu Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/inode.c | 8 ++++---- drivers/staging/erofs/xattr.c | 25 ++++++++++++++++++++----- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c index d7fbf5f4600f..f99954dbfdb5 100644 --- a/drivers/staging/erofs/inode.c +++ b/drivers/staging/erofs/inode.c @@ -185,16 +185,16 @@ static int fill_inode(struct inode *inode, int isdir) /* setup the new inode */ if (S_ISREG(inode->i_mode)) { #ifdef CONFIG_EROFS_FS_XATTR - if (vi->xattr_isize) - inode->i_op = &erofs_generic_xattr_iops; + inode->i_op = &erofs_generic_xattr_iops; #endif inode->i_fop = &generic_ro_fops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = #ifdef CONFIG_EROFS_FS_XATTR - vi->xattr_isize ? &erofs_dir_xattr_iops : -#endif + &erofs_dir_xattr_iops; +#else &erofs_dir_iops; +#endif inode->i_fop = &erofs_dir_fops; } else if (S_ISLNK(inode->i_mode)) { /* by default, page_get_link is used for symlink */ diff --git a/drivers/staging/erofs/xattr.c b/drivers/staging/erofs/xattr.c index 59bc5641c4e7..1c9498e38f0e 100644 --- a/drivers/staging/erofs/xattr.c +++ b/drivers/staging/erofs/xattr.c @@ -56,7 +56,26 @@ static int init_inode_xattrs(struct inode *inode) return 0; vi = EROFS_V(inode); - BUG_ON(!vi->xattr_isize); + + /* + * bypass all xattr operations if ->xattr_isize is not greater than + * sizeof(struct erofs_xattr_ibody_header), in detail: + * 1) it is not enough to contain erofs_xattr_ibody_header then + * ->xattr_isize should be 0 (it means no xattr); + * 2) it is just to contain erofs_xattr_ibody_header, which is on-disk + * undefined right now (maybe use later with some new sb feature). + */ + if (vi->xattr_isize == sizeof(struct erofs_xattr_ibody_header)) { + errln("xattr_isize %d of nid %llu is not supported yet", + vi->xattr_isize, vi->nid); + return -ENOTSUPP; + } else if (vi->xattr_isize < sizeof(struct erofs_xattr_ibody_header)) { + if (unlikely(vi->xattr_isize)) { + DBG_BUGON(1); + return -EIO; /* xattr ondisk layout error */ + } + return -ENOATTR; + } sb = inode->i_sb; sbi = EROFS_SB(sb); @@ -424,7 +443,6 @@ static int erofs_xattr_generic_get(const struct xattr_handler *handler, struct dentry *unused, struct inode *inode, const char *name, void *buffer, size_t size) { - struct erofs_vnode *const vi = EROFS_V(inode); struct erofs_sb_info *const sbi = EROFS_I_SB(inode); switch (handler->flags) { @@ -442,9 +460,6 @@ static int erofs_xattr_generic_get(const struct xattr_handler *handler, return -EINVAL; } - if (!vi->xattr_isize) - return -ENOATTR; - return erofs_getxattr(inode, handler->flags, name, buffer, size); } -- cgit From 609398266c5426db2622dc43db2c95855d3b8e6c Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Mon, 14 Jan 2019 19:40:24 +0800 Subject: staging: erofs: remove unneeded inode_operations Currently, EROFS uses generic iops when xattr is off, it seems unnecessary and a lot of extra code is there. Let's follow what other filesystems do instead. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/inode.c | 38 ++++++++++++------------------------ drivers/staging/erofs/internal.h | 42 +++++++++++++++++----------------------- drivers/staging/erofs/namei.c | 4 ---- drivers/staging/erofs/xattr.h | 4 ---- 4 files changed, 30 insertions(+), 58 deletions(-) diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c index f99954dbfdb5..4f04f7c38cf2 100644 --- a/drivers/staging/erofs/inode.c +++ b/drivers/staging/erofs/inode.c @@ -184,32 +184,18 @@ static int fill_inode(struct inode *inode, int isdir) if (!err) { /* setup the new inode */ if (S_ISREG(inode->i_mode)) { -#ifdef CONFIG_EROFS_FS_XATTR - inode->i_op = &erofs_generic_xattr_iops; -#endif + inode->i_op = &erofs_generic_iops; inode->i_fop = &generic_ro_fops; } else if (S_ISDIR(inode->i_mode)) { - inode->i_op = -#ifdef CONFIG_EROFS_FS_XATTR - &erofs_dir_xattr_iops; -#else - &erofs_dir_iops; -#endif + inode->i_op = &erofs_dir_iops; inode->i_fop = &erofs_dir_fops; } else if (S_ISLNK(inode->i_mode)) { /* by default, page_get_link is used for symlink */ - inode->i_op = -#ifdef CONFIG_EROFS_FS_XATTR - &erofs_symlink_xattr_iops, -#else - &page_symlink_inode_operations; -#endif + inode->i_op = &erofs_symlink_iops; inode_nohighmem(inode); } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { -#ifdef CONFIG_EROFS_FS_XATTR - inode->i_op = &erofs_special_inode_operations; -#endif + inode->i_op = &erofs_generic_iops; init_special_inode(inode, inode->i_mode, inode->i_rdev); } else { err = -EIO; @@ -297,23 +283,23 @@ struct inode *erofs_iget(struct super_block *sb, return inode; } +const struct inode_operations erofs_generic_iops = { #ifdef CONFIG_EROFS_FS_XATTR -const struct inode_operations erofs_generic_xattr_iops = { .listxattr = erofs_listxattr, +#endif }; -const struct inode_operations erofs_symlink_xattr_iops = { +const struct inode_operations erofs_symlink_iops = { .get_link = page_get_link, +#ifdef CONFIG_EROFS_FS_XATTR .listxattr = erofs_listxattr, +#endif }; -const struct inode_operations erofs_special_inode_operations = { - .listxattr = erofs_listxattr, -}; - -const struct inode_operations erofs_fast_symlink_xattr_iops = { +const struct inode_operations erofs_fast_symlink_iops = { .get_link = simple_get_link, +#ifdef CONFIG_EROFS_FS_XATTR .listxattr = erofs_listxattr, -}; #endif +}; diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 192f4028d85d..ae4f2555f497 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -414,8 +414,6 @@ static inline bool is_inode_layout_inline(struct inode *inode) } extern const struct super_operations erofs_sops; -extern const struct inode_operations erofs_dir_iops; -extern const struct file_operations erofs_dir_fops; extern const struct address_space_operations erofs_raw_access_aops; #ifdef CONFIG_EROFS_FS_ZIP @@ -559,37 +557,33 @@ static inline unsigned long erofs_inode_hash(erofs_nid_t nid) extern struct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid, bool dir); -/* dir.c */ -int erofs_namei(struct inode *dir, struct qstr *name, - erofs_nid_t *nid, unsigned *d_type); - -#ifdef CONFIG_EROFS_FS_XATTR -/* xattr.c */ -extern const struct xattr_handler *erofs_xattr_handlers[]; - -/* symlink and special inode */ -extern const struct inode_operations erofs_symlink_xattr_iops; -extern const struct inode_operations erofs_fast_symlink_xattr_iops; -extern const struct inode_operations erofs_special_inode_operations; -#endif +extern const struct inode_operations erofs_generic_iops; +extern const struct inode_operations erofs_symlink_iops; +extern const struct inode_operations erofs_fast_symlink_iops; static inline void set_inode_fast_symlink(struct inode *inode) { -#ifdef CONFIG_EROFS_FS_XATTR - inode->i_op = &erofs_fast_symlink_xattr_iops; -#else - inode->i_op = &simple_symlink_inode_operations; -#endif + inode->i_op = &erofs_fast_symlink_iops; } static inline bool is_inode_fast_symlink(struct inode *inode) { + return inode->i_op == &erofs_fast_symlink_iops; +} + +/* namei.c */ +extern const struct inode_operations erofs_dir_iops; + +int erofs_namei(struct inode *dir, struct qstr *name, + erofs_nid_t *nid, unsigned int *d_type); + +/* dir.c */ +extern const struct file_operations erofs_dir_fops; + #ifdef CONFIG_EROFS_FS_XATTR - return inode->i_op == &erofs_fast_symlink_xattr_iops; -#else - return inode->i_op == &simple_symlink_inode_operations; +/* xattr.c */ +extern const struct xattr_handler *erofs_xattr_handlers[]; #endif -} static inline void *erofs_vmap(struct page **pages, unsigned int count) { diff --git a/drivers/staging/erofs/namei.c b/drivers/staging/erofs/namei.c index 5596c52e246d..7fed1f996ab0 100644 --- a/drivers/staging/erofs/namei.c +++ b/drivers/staging/erofs/namei.c @@ -235,10 +235,6 @@ static struct dentry *erofs_lookup(struct inode *dir, const struct inode_operations erofs_dir_iops = { .lookup = erofs_lookup, -}; - -const struct inode_operations erofs_dir_xattr_iops = { - .lookup = erofs_lookup, #ifdef CONFIG_EROFS_FS_XATTR .listxattr = erofs_listxattr, #endif diff --git a/drivers/staging/erofs/xattr.h b/drivers/staging/erofs/xattr.h index 0c7379282fc5..810fc947701d 100644 --- a/drivers/staging/erofs/xattr.h +++ b/drivers/staging/erofs/xattr.h @@ -68,10 +68,6 @@ static const struct xattr_handler *xattr_handler_map[] = { } #ifdef CONFIG_EROFS_FS_XATTR - -extern const struct inode_operations erofs_generic_xattr_iops; -extern const struct inode_operations erofs_dir_xattr_iops; - int erofs_getxattr(struct inode *, int, const char *, void *, size_t); ssize_t erofs_listxattr(struct dentry *, char *, size_t); #else -- cgit From 6af7b4830569a125e65a1123a3ac1db44e999929 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Mon, 14 Jan 2019 19:40:25 +0800 Subject: staging: erofs: move erofs_xattr_handlers to xattr.h Let's move independent xattr-related stuffs to xattr.h. No logic changes. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 5 ----- drivers/staging/erofs/super.c | 1 + drivers/staging/erofs/xattr.h | 2 ++ 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index ae4f2555f497..99b50b981335 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -580,11 +580,6 @@ int erofs_namei(struct inode *dir, struct qstr *name, /* dir.c */ extern const struct file_operations erofs_dir_fops; -#ifdef CONFIG_EROFS_FS_XATTR -/* xattr.c */ -extern const struct xattr_handler *erofs_xattr_handlers[]; -#endif - static inline void *erofs_vmap(struct page **pages, unsigned int count) { #ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 1c2eb69682ef..45c7f6ddb9f5 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -16,6 +16,7 @@ #include #include #include "internal.h" +#include "xattr.h" #define CREATE_TRACE_POINTS #include diff --git a/drivers/staging/erofs/xattr.h b/drivers/staging/erofs/xattr.h index 810fc947701d..634dae9aaa0b 100644 --- a/drivers/staging/erofs/xattr.h +++ b/drivers/staging/erofs/xattr.h @@ -68,6 +68,8 @@ static const struct xattr_handler *xattr_handler_map[] = { } #ifdef CONFIG_EROFS_FS_XATTR +extern const struct xattr_handler *erofs_xattr_handlers[]; + int erofs_getxattr(struct inode *, int, const char *, void *, size_t); ssize_t erofs_listxattr(struct dentry *, char *, size_t); #else -- cgit From 3b423417d0d1d5abd46dfc7c3df9977bcb89f3c0 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 15 Jan 2019 09:42:21 +0800 Subject: staging: erofs: clean up erofs_map_blocks_iter This patch cleans up erofs_map_blocks* function and structure family, just simply the code, no logic change. Reviewed-by: Gao Xiang Signed-off-by: Chao Yu Signed-off-by: Gao Xiang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/data.c | 31 +++++-------------------------- drivers/staging/erofs/internal.h | 28 +++++++++++++++------------- drivers/staging/erofs/unzip_vle.c | 30 +++++++++++++++--------------- 3 files changed, 35 insertions(+), 54 deletions(-) diff --git a/drivers/staging/erofs/data.c b/drivers/staging/erofs/data.c index 329fa4fa3e9c..9c471f08ffd4 100644 --- a/drivers/staging/erofs/data.c +++ b/drivers/staging/erofs/data.c @@ -165,37 +165,16 @@ err_out: return err; } -int erofs_map_blocks_iter(struct inode *inode, - struct erofs_map_blocks *map, - struct page **mpage_ret, int flags) -{ - /* by default, reading raw data never use erofs_map_blocks_iter */ - if (unlikely(!is_inode_layout_compression(inode))) { - if (*mpage_ret) - put_page(*mpage_ret); - *mpage_ret = NULL; - - return erofs_map_blocks(inode, map, flags); - } - -#ifdef CONFIG_EROFS_FS_ZIP - return z_erofs_map_blocks_iter(inode, map, mpage_ret, flags); -#else - /* data compression is not available */ - return -ENOTSUPP; -#endif -} - int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map, int flags) { if (unlikely(is_inode_layout_compression(inode))) { - struct page *mpage = NULL; - int err; + int err = z_erofs_map_blocks_iter(inode, map, flags); - err = erofs_map_blocks_iter(inode, map, &mpage, flags); - if (mpage) - put_page(mpage); + if (map->mpage) { + put_page(map->mpage); + map->mpage = NULL; + } return err; } return erofs_map_blocks_flatmode(inode, map, flags); diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 99b50b981335..c3de24e7fb67 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -461,11 +461,26 @@ struct erofs_map_blocks { u64 m_plen, m_llen; unsigned int m_flags; + + struct page *mpage; }; /* Flags used by erofs_map_blocks() */ #define EROFS_GET_BLOCKS_RAW 0x0001 +#ifdef CONFIG_EROFS_FS_ZIP +int z_erofs_map_blocks_iter(struct inode *inode, + struct erofs_map_blocks *map, + int flags); +#else +static inline int z_erofs_map_blocks_iter(struct inode *inode, + struct erofs_map_blocks *map, + int flags) +{ + return -ENOTSUPP; +} +#endif + /* data.c */ static inline struct bio * erofs_grab_bio(struct super_block *sb, @@ -522,19 +537,6 @@ static inline struct page *erofs_get_meta_page_nofail(struct super_block *sb, } extern int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int); -extern int erofs_map_blocks_iter(struct inode *, struct erofs_map_blocks *, - struct page **, int); - -struct erofs_map_blocks_iter { - struct erofs_map_blocks map; - struct page *mpage; -}; - -#ifdef CONFIG_EROFS_FS_ZIP -extern int z_erofs_map_blocks_iter(struct inode *, - struct erofs_map_blocks *, - struct page **, int); -#endif static inline struct page * erofs_get_inline_page(struct inode *inode, diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c index 584612b47369..29b3b1dc67f1 100644 --- a/drivers/staging/erofs/unzip_vle.c +++ b/drivers/staging/erofs/unzip_vle.c @@ -636,7 +636,7 @@ struct z_erofs_vle_frontend { struct inode *const inode; struct z_erofs_vle_work_builder builder; - struct erofs_map_blocks_iter m_iter; + struct erofs_map_blocks map; z_erofs_vle_owned_workgrp_t owned_head; @@ -647,8 +647,9 @@ struct z_erofs_vle_frontend { #define VLE_FRONTEND_INIT(__i) { \ .inode = __i, \ - .m_iter = { \ - { .m_llen = 0, .m_plen = 0 }, \ + .map = { \ + .m_llen = 0, \ + .m_plen = 0, \ .mpage = NULL \ }, \ .builder = VLE_WORK_BUILDER_INIT(), \ @@ -681,8 +682,7 @@ static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, { struct super_block *const sb = fe->inode->i_sb; struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb); - struct erofs_map_blocks_iter *const m = &fe->m_iter; - struct erofs_map_blocks *const map = &m->map; + struct erofs_map_blocks *const map = &fe->map; struct z_erofs_vle_work_builder *const builder = &fe->builder; const loff_t offset = page_offset(page); @@ -715,7 +715,7 @@ repeat: map->m_la = offset + cur; map->m_llen = 0; - err = erofs_map_blocks_iter(fe->inode, map, &m->mpage, 0); + err = z_erofs_map_blocks_iter(fe->inode, map, 0); if (unlikely(err)) goto err_out; @@ -1484,8 +1484,8 @@ static int z_erofs_vle_normalaccess_readpage(struct file *file, z_erofs_submit_and_unzip(&f, &pagepool, true); out: - if (f.m_iter.mpage) - put_page(f.m_iter.mpage); + if (f.map.mpage) + put_page(f.map.mpage); /* clean up the remaining free pages */ put_pages_list(&pagepool); @@ -1555,8 +1555,8 @@ static int z_erofs_vle_normalaccess_readpages(struct file *filp, z_erofs_submit_and_unzip(&f, &pagepool, sync); - if (f.m_iter.mpage) - put_page(f.m_iter.mpage); + if (f.map.mpage) + put_page(f.map.mpage); /* clean up the remaining free pages */ put_pages_list(&pagepool); @@ -1701,14 +1701,14 @@ vle_get_logical_extent_head(const struct vle_map_blocks_iter_ctx *ctx, int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, - struct page **mpage_ret, int flags) + int flags) { void *kaddr; const struct vle_map_blocks_iter_ctx ctx = { .inode = inode, .sb = inode->i_sb, .clusterbits = EROFS_I_SB(inode)->clusterbits, - .mpage_ret = mpage_ret, + .mpage_ret = &map->mpage, .kaddr_ret = &kaddr }; const unsigned int clustersize = 1 << ctx.clusterbits; @@ -1722,7 +1722,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, /* initialize `pblk' to keep gcc from printing foolish warnings */ erofs_blk_t mblk, pblk = 0; - struct page *mpage = *mpage_ret; + struct page *mpage = map->mpage; struct z_erofs_vle_decompressed_index *di; unsigned int cluster_type, logical_cluster_ofs; int err = 0; @@ -1758,7 +1758,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, err = PTR_ERR(mpage); goto out; } - *mpage_ret = mpage; + map->mpage = mpage; } else { lock_page(mpage); DBG_BUGON(!PageUptodate(mpage)); @@ -1818,7 +1818,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, /* get the correspoinding first chunk */ err = vle_get_logical_extent_head(&ctx, lcn, &ofs, &pblk, &map->m_flags); - mpage = *mpage_ret; + mpage = map->mpage; if (unlikely(err)) { if (mpage) -- cgit From e6718f686ed4b9e48c26bf3cda220a2c98df20e3 Mon Sep 17 00:00:00 2001 From: Brajeswar Ghosh Date: Wed, 9 Jan 2019 20:55:59 +0530 Subject: staging/android/vsoc: Remove duplicate header Remove linux/mutex.h which is included more than once Signed-off-by: Brajeswar Ghosh Acked-by: Souptick Joarder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/vsoc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/android/vsoc.c b/drivers/staging/android/vsoc.c index 22571abcaa4e..8a75bd27c413 100644 --- a/drivers/staging/android/vsoc.c +++ b/drivers/staging/android/vsoc.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include "uapi/vsoc_shm.h" -- cgit From 891fd847605d4d7e8aef07db39f1868b5a70e047 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 14 Jan 2019 22:40:58 -0600 Subject: staging: rtl8188eu: Replace kzalloc with kcalloc Replace kzalloc() function with its 2-factor argument form, kcalloc(). This patch replaces cases of: kzalloc(a * b, gfp) with: kcalloc(a, b, gfp) This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_efuse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index b7be71f904ed..51c3dd6d7ffb 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -88,7 +88,9 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) if (!efuseTbl) return; - tmp = kzalloc(EFUSE_MAX_SECTION_88E * (sizeof(void *) + EFUSE_MAX_WORD_UNIT * sizeof(u16)), GFP_KERNEL); + tmp = kcalloc(EFUSE_MAX_SECTION_88E, + sizeof(void *) + EFUSE_MAX_WORD_UNIT * sizeof(u16), + GFP_KERNEL); if (!tmp) { DBG_88E("%s: alloc eFuseWord fail!\n", __func__); goto eFuseWord_failed; -- cgit From 47ed91d3a26825cf276c490b1e4f7588111370d4 Mon Sep 17 00:00:00 2001 From: Alexander Schroth Date: Thu, 10 Jan 2019 15:57:22 +0100 Subject: staging: comedi: ni_pcidio: make defines uppercase According to the Linux coding guidelines, defines should be written in uppercase. This patch converts all define-statements in the ni_pcidio.c file to uppercase, thus matching the coding style of the kernel. Signed-off-by: Alexander Schroth Signed-off-by: Marco Ammon Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcidio.c | 444 +++++++++++++++-------------- 1 file changed, 223 insertions(+), 221 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index b9a0dc6eac44..4bdef87d5dd7 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -49,116 +49,117 @@ /* defines for the PCI-DIO-32HS */ -#define Window_Address 4 /* W */ -#define Interrupt_And_Window_Status 4 /* R */ -#define IntStatus1 BIT(0) -#define IntStatus2 BIT(1) -#define WindowAddressStatus_mask 0x7c - -#define Master_DMA_And_Interrupt_Control 5 /* W */ -#define InterruptLine(x) ((x) & 3) -#define OpenInt BIT(2) -#define Group_Status 5 /* R */ -#define DataLeft BIT(0) -#define Req BIT(2) -#define StopTrig BIT(3) - -#define Group_1_Flags 6 /* R */ -#define Group_2_Flags 7 /* R */ -#define TransferReady BIT(0) -#define CountExpired BIT(1) -#define Waited BIT(5) -#define PrimaryTC BIT(6) -#define SecondaryTC BIT(7) +#define WINDOW_ADDRESS 4 /* W */ +#define INTERRUPT_AND_WINDOW_STATUS 4 /* R */ +#define INT_STATUS_1 BIT(0) +#define INT_STATUS_2 BIT(1) +#define WINDOW_ADDRESS_STATUS_MASK 0x7c + +#define MASTER_DMA_AND_INTERRUPT_CONTROL 5 /* W */ +#define INTERRUPT_LINE(x) ((x) & 3) +#define OPEN_INT BIT(2) +#define GROUP_STATUS 5 /* R */ +#define DATA_LEFT BIT(0) +#define REQ BIT(2) +#define STOP_TRIG BIT(3) + +#define GROUP_1_FLAGS 6 /* R */ +#define GROUP_2_FLAGS 7 /* R */ +#define TRANSFER_READY BIT(0) +#define COUNT_EXPIRED BIT(1) +#define WAITED BIT(5) +#define PRIMARY_TC BIT(6) +#define SECONDARY_TC BIT(7) /* #define SerialRose */ /* #define ReqRose */ /* #define Paused */ -#define Group_1_First_Clear 6 /* W */ -#define Group_2_First_Clear 7 /* W */ -#define ClearWaited BIT(3) -#define ClearPrimaryTC BIT(4) -#define ClearSecondaryTC BIT(5) -#define DMAReset BIT(6) -#define FIFOReset BIT(7) -#define ClearAll 0xf8 - -#define Group_1_FIFO 8 /* W */ -#define Group_2_FIFO 12 /* W */ - -#define Transfer_Count 20 -#define Chip_ID_D 24 -#define Chip_ID_I 25 -#define Chip_ID_O 26 -#define Chip_Version 27 -#define Port_IO(x) (28 + (x)) -#define Port_Pin_Directions(x) (32 + (x)) -#define Port_Pin_Mask(x) (36 + (x)) -#define Port_Pin_Polarities(x) (40 + (x)) - -#define Master_Clock_Routing 45 -#define RTSIClocking(x) (((x) & 3) << 4) - -#define Group_1_Second_Clear 46 /* W */ -#define Group_2_Second_Clear 47 /* W */ -#define ClearExpired BIT(0) - -#define Port_Pattern(x) (48 + (x)) - -#define Data_Path 64 -#define FIFOEnableA BIT(0) -#define FIFOEnableB BIT(1) -#define FIFOEnableC BIT(2) -#define FIFOEnableD BIT(3) -#define Funneling(x) (((x) & 3) << 4) -#define GroupDirection BIT(7) - -#define Protocol_Register_1 65 -#define OpMode Protocol_Register_1 -#define RunMode(x) ((x) & 7) -#define Numbered BIT(3) - -#define Protocol_Register_2 66 -#define ClockReg Protocol_Register_2 -#define ClockLine(x) (((x) & 3) << 5) -#define InvertStopTrig BIT(7) -#define DataLatching(x) (((x) & 3) << 5) - -#define Protocol_Register_3 67 -#define Sequence Protocol_Register_3 - -#define Protocol_Register_14 68 /* 16 bit */ -#define ClockSpeed Protocol_Register_14 - -#define Protocol_Register_4 70 -#define ReqReg Protocol_Register_4 -#define ReqConditioning(x) (((x) & 7) << 3) - -#define Protocol_Register_5 71 -#define BlockMode Protocol_Register_5 +#define GROUP_1_FIRST_CLEAR 6 /* W */ +#define GROUP_2_FIRST_CLEAR 7 /* W */ +#define CLEAR_WAITED BIT(3) +#define CLEAR_PRIMARY_TC BIT(4) +#define CLEAR_SECONDARY_TC BIT(5) +#define DMA_RESET BIT(6) +#define FIFO_RESET BIT(7) +#define CLEAR_ALL 0xf8 + +#define GROUP_1_FIFO 8 /* W */ +#define GROUP_2_FIFO 12 /* W */ + +#define TRANSFER_COUNT 20 +#define CHIP_ID_D 24 +#define CHIP_ID_I 25 +#define CHIP_ID_O 26 +#define CHIP_VERSION 27 +#define PORT_IO(x) (28 + (x)) +#define PORT_PIN_DIRECTIONS(x) (32 + (x)) +#define PORT_PIN_MASK(x) (36 + (x)) +#define PORT_PIN_POLARITIES(x) (40 + (x)) + +#define MASTER_CLOCK_ROUTING 45 +#define RTSI_CLOCKING(x) (((x) & 3) << 4) + +#define GROUP_1_SECOND_CLEAR 46 /* W */ +#define GROUP_2_SECOND_CLEAR 47 /* W */ +#define CLEAR_EXPIRED BIT(0) + +#define PORT_PATTERN(x) (48 + (x)) + +#define DATA_PATH 64 +#define FIFO_ENABLE_A BIT(0) +#define FIFO_ENABLE_B BIT(1) +#define FIFO_ENABLE_C BIT(2) +#define FIFO_ENABLE_D BIT(3) +#define FUNNELING(x) (((x) & 3) << 4) +#define GROUP_DIRECTION BIT(7) + +#define PROTOCOL_REGISTER_1 65 +#define OP_MODE PROTOCOL_REGISTER_1 +#define RUN_MODE(x) ((x) & 7) +#define NUMBERED BIT(3) + +#define PROTOCOL_REGISTER_2 66 +#define CLOCK_REG PROTOCOL_REGISTER_2 +#define CLOCK_LINE(x) (((x) & 3) << 5) +#define INVERT_STOP_TRIG BIT(7) +#define DATA_LATCHING(x) (((x) & 3) << 5) + +#define PROTOCOL_REGISTER_3 67 +#define SEQUENCE PROTOCOL_REGISTER_3 + +#define PROTOCOL_REGISTER_14 68 /* 16 bit */ +#define CLOCK_SPEED PROTOCOL_REGISTER_14 + +#define PROTOCOL_REGISTER_4 70 +#define REQ_REG PROTOCOL_REGISTER_4 +#define REQ_CONDITIONING(x) (((x) & 7) << 3) + +#define PROTOCOL_REGISTER_5 71 +#define BLOCK_MODE PROTOCOL_REGISTER_5 #define FIFO_Control 72 -#define ReadyLevel(x) ((x) & 7) - -#define Protocol_Register_6 73 -#define LinePolarities Protocol_Register_6 -#define InvertAck BIT(0) -#define InvertReq BIT(1) -#define InvertClock BIT(2) -#define InvertSerial BIT(3) -#define OpenAck BIT(4) -#define OpenClock BIT(5) - -#define Protocol_Register_7 74 -#define AckSer Protocol_Register_7 -#define AckLine(x) (((x) & 3) << 2) -#define ExchangePins BIT(7) - -#define Interrupt_Control 75 - /* bits same as flags */ - -#define DMA_Line_Control_Group1 76 -#define DMA_Line_Control_Group2 108 +#define READY_LEVEL(x) ((x) & 7) + +#define PROTOCOL_REGISTER_6 73 +#define LINE_POLARITIES PROTOCOL_REGISTER_6 +#define INVERT_ACK BIT(0) +#define INVERT_REQ BIT(1) +#define INVERT_CLOCK BIT(2) +#define INVERT_SERIAL BIT(3) +#define OPEN_ACK BIT(4) +#define OPEN_CLOCK BIT(5) + +#define PROTOCOL_REGISTER_7 74 +#define ACK_SER PROTOCOL_REGISTER_7 +#define ACK_LINE(x) (((x) & 3) << 2) +#define EXCHANGE_PINS BIT(7) + +#define INTERRUPT_CONTROL 75 +/* bits same as flags */ + +#define DMA_LINE_CONTROL_GROUP1 76 +#define DMA_LINE_CONTROL_GROUP2 108 + /* channel zero is none */ static inline unsigned int primary_DMAChannel_bits(unsigned int channel) { @@ -170,41 +171,41 @@ static inline unsigned int secondary_DMAChannel_bits(unsigned int channel) return (channel << 2) & 0xc; } -#define Transfer_Size_Control 77 -#define TransferWidth(x) ((x) & 3) -#define TransferLength(x) (((x) & 3) << 3) -#define RequireRLevel BIT(5) +#define TRANSFER_SIZE_CONTROL 77 +#define TRANSFER_WIDTH(x) ((x) & 3) +#define TRANSFER_LENGTH(x) (((x) & 3) << 3) +#define REQUIRE_R_LEVEL BIT(5) -#define Protocol_Register_15 79 -#define DAQOptions Protocol_Register_15 -#define StartSource(x) ((x) & 0x3) -#define InvertStart BIT(2) -#define StopSource(x) (((x) & 0x3) << 3) -#define ReqStart BIT(6) -#define PreStart BIT(7) +#define PROTOCOL_REGISTER_15 79 +#define DAQ_OPTIONS PROTOCOL_REGISTER_15 +#define START_SOURCE(x) ((x) & 0x3) +#define INVERT_START BIT(2) +#define STOP_SOURCE(x) (((x) & 0x3) << 3) +#define REQ_START BIT(6) +#define PRE_START BIT(7) -#define Pattern_Detection 81 -#define DetectionMethod BIT(0) -#define InvertMatch BIT(1) -#define IE_Pattern_Detection BIT(2) +#define PATTERN_DETECTION 81 +#define DETECTION_METHOD BIT(0) +#define INVERT_MATCH BIT(1) +#define IE_PATTERN_DETECTION BIT(2) -#define Protocol_Register_9 82 -#define ReqDelay Protocol_Register_9 +#define PROTOCOL_REGISTER_9 82 +#define REQ_DELAY PROTOCOL_REGISTER_9 -#define Protocol_Register_10 83 -#define ReqNotDelay Protocol_Register_10 +#define PROTOCOL_REGISTER_10 83 +#define REQ_NOT_DELAY PROTOCOL_REGISTER_10 -#define Protocol_Register_11 84 -#define AckDelay Protocol_Register_11 +#define PROTOCOL_REGISTER_11 84 +#define ACK_DELAY PROTOCOL_REGISTER_11 -#define Protocol_Register_12 85 -#define AckNotDelay Protocol_Register_12 +#define PROTOCOL_REGISTER_12 85 +#define ACK_NOT_DELAY PROTOCOL_REGISTER_12 -#define Protocol_Register_13 86 -#define Data1Delay Protocol_Register_13 +#define PROTOCOL_REGISTER_13 86 +#define DATA_1_DELAY PROTOCOL_REGISTER_13 -#define Protocol_Register_8 88 /* 32 bit */ -#define StartDelay Protocol_Register_8 +#define PROTOCOL_REGISTER_8 88 /* 32 bit */ +#define START_DELAY PROTOCOL_REGISTER_8 /* Firmware files for PCI-6524 */ #define FW_PCI_6534_MAIN "ni6534a.bin" @@ -246,9 +247,10 @@ enum FPGA_Control_Bits { #define TIMER_BASE 50 /* nanoseconds */ #ifdef USE_DMA -#define IntEn (CountExpired | Waited | PrimaryTC | SecondaryTC) +#define INT_EN (COUNT_EXPIRED | WAITED | PRIMARY_TC | SECONDARY_TC) #else -#define IntEn (TransferReady | CountExpired | Waited | PrimaryTC | SecondaryTC) +#define INT_EN (TRANSFER_READY | COUNT_EXPIRED | WAITED \ + | PRIMARY_TC | SECONDARY_TC) #endif enum nidio_boardid { @@ -283,7 +285,7 @@ struct nidio96_private { struct mite *mite; int boardtype; int dio; - unsigned short OpModeBits; + unsigned short OP_MODEBits; struct mite_channel *di_mite_chan; struct mite_ring *di_mite_ring; spinlock_t mite_channel_lock; @@ -307,7 +309,7 @@ static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev) devpriv->di_mite_chan->dir = COMEDI_INPUT; writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) | secondary_DMAChannel_bits(devpriv->di_mite_chan->channel), - dev->mmio + DMA_Line_Control_Group1); + dev->mmio + DMA_LINE_CONTROL_GROUP1); mmiowb(); spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); return 0; @@ -324,7 +326,7 @@ static void ni_pcidio_release_di_mite_channel(struct comedi_device *dev) devpriv->di_mite_chan = NULL; writeb(primary_DMAChannel_bits(0) | secondary_DMAChannel_bits(0), - dev->mmio + DMA_Line_Control_Group1); + dev->mmio + DMA_LINE_CONTROL_GROUP1); mmiowb(); } spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); @@ -391,8 +393,8 @@ static irqreturn_t nidio_interrupt(int irq, void *d) /* Lock to avoid race with comedi_poll */ spin_lock(&dev->spinlock); - status = readb(dev->mmio + Interrupt_And_Window_Status); - flags = readb(dev->mmio + Group_1_Flags); + status = readb(dev->mmio + INTERRUPT_AND_WINDOW_STATUS); + flags = readb(dev->mmio + GROUP_1_FLAGS); spin_lock(&devpriv->mite_channel_lock); if (devpriv->di_mite_chan) { @@ -401,63 +403,63 @@ static irqreturn_t nidio_interrupt(int irq, void *d) } spin_unlock(&devpriv->mite_channel_lock); - while (status & DataLeft) { + while (status & DATA_LEFT) { work++; if (work > 20) { dev_dbg(dev->class_dev, "too much work in interrupt\n"); writeb(0x00, - dev->mmio + Master_DMA_And_Interrupt_Control); + dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL); break; } - flags &= IntEn; + flags &= INT_EN; - if (flags & TransferReady) { - while (flags & TransferReady) { + if (flags & TRANSFER_READY) { + while (flags & TRANSFER_READY) { work++; if (work > 100) { dev_dbg(dev->class_dev, "too much work in interrupt\n"); writeb(0x00, dev->mmio + - Master_DMA_And_Interrupt_Control + MASTER_DMA_AND_INTERRUPT_CONTROL ); goto out; } - auxdata = readl(dev->mmio + Group_1_FIFO); + auxdata = readl(dev->mmio + GROUP_1_FIFO); comedi_buf_write_samples(s, &auxdata, 1); - flags = readb(dev->mmio + Group_1_Flags); + flags = readb(dev->mmio + GROUP_1_FLAGS); } } - if (flags & CountExpired) { - writeb(ClearExpired, dev->mmio + Group_1_Second_Clear); + if (flags & COUNT_EXPIRED) { + writeb(CLEAR_EXPIRED, dev->mmio + GROUP_1_SECOND_CLEAR); async->events |= COMEDI_CB_EOA; - writeb(0x00, dev->mmio + OpMode); + writeb(0x00, dev->mmio + OP_MODE); break; - } else if (flags & Waited) { - writeb(ClearWaited, dev->mmio + Group_1_First_Clear); + } else if (flags & WAITED) { + writeb(CLEAR_WAITED, dev->mmio + GROUP_1_FIRST_CLEAR); async->events |= COMEDI_CB_ERROR; break; - } else if (flags & PrimaryTC) { - writeb(ClearPrimaryTC, - dev->mmio + Group_1_First_Clear); + } else if (flags & PRIMARY_TC) { + writeb(CLEAR_PRIMARY_TC, + dev->mmio + GROUP_1_FIRST_CLEAR); async->events |= COMEDI_CB_EOA; - } else if (flags & SecondaryTC) { - writeb(ClearSecondaryTC, - dev->mmio + Group_1_First_Clear); + } else if (flags & SECONDARY_TC) { + writeb(CLEAR_SECONDARY_TC, + dev->mmio + GROUP_1_FIRST_CLEAR); async->events |= COMEDI_CB_EOA; } - flags = readb(dev->mmio + Group_1_Flags); - status = readb(dev->mmio + Interrupt_And_Window_Status); + flags = readb(dev->mmio + GROUP_1_FLAGS); + status = readb(dev->mmio + INTERRUPT_AND_WINDOW_STATUS); } out: comedi_handle_events(dev, s); #if 0 if (!tag) - writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control); + writeb(0x03, dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL); #endif spin_unlock(&dev->spinlock); @@ -484,7 +486,7 @@ static int ni_pcidio_insn_config(struct comedi_device *dev, if (ret) return ret; - writel(s->io_bits, dev->mmio + Port_Pin_Directions(0)); + writel(s->io_bits, dev->mmio + PORT_PIN_DIRECTIONS(0)); return insn->n; } @@ -495,9 +497,9 @@ static int ni_pcidio_insn_bits(struct comedi_device *dev, unsigned int *data) { if (comedi_dio_update_state(s, data)) - writel(s->state, dev->mmio + Port_IO(0)); + writel(s->state, dev->mmio + PORT_IO(0)); - data[1] = readl(dev->mmio + Port_IO(0)); + data[1] = readl(dev->mmio + PORT_IO(0)); return insn->n; } @@ -609,7 +611,7 @@ static int ni_pcidio_inttrig(struct comedi_device *dev, if (trig_num != cmd->start_arg) return -EINVAL; - writeb(devpriv->OpModeBits, dev->mmio + OpMode); + writeb(devpriv->OP_MODEBits, dev->mmio + OP_MODE); s->async->inttrig = NULL; return 1; @@ -621,78 +623,78 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_cmd *cmd = &s->async->cmd; /* XXX configure ports for input */ - writel(0x0000, dev->mmio + Port_Pin_Directions(0)); + writel(0x0000, dev->mmio + PORT_PIN_DIRECTIONS(0)); if (1) { /* enable fifos A B C D */ - writeb(0x0f, dev->mmio + Data_Path); + writeb(0x0f, dev->mmio + DATA_PATH); /* set transfer width a 32 bits */ - writeb(TransferWidth(0) | TransferLength(0), - dev->mmio + Transfer_Size_Control); + writeb(TRANSFER_WIDTH(0) | TRANSFER_LENGTH(0), + dev->mmio + TRANSFER_SIZE_CONTROL); } else { - writeb(0x03, dev->mmio + Data_Path); - writeb(TransferWidth(3) | TransferLength(0), - dev->mmio + Transfer_Size_Control); + writeb(0x03, dev->mmio + DATA_PATH); + writeb(TRANSFER_WIDTH(3) | TRANSFER_LENGTH(0), + dev->mmio + TRANSFER_SIZE_CONTROL); } /* protocol configuration */ if (cmd->scan_begin_src == TRIG_TIMER) { /* page 4-5, "input with internal REQs" */ - writeb(0, dev->mmio + OpMode); - writeb(0x00, dev->mmio + ClockReg); - writeb(1, dev->mmio + Sequence); - writeb(0x04, dev->mmio + ReqReg); - writeb(4, dev->mmio + BlockMode); - writeb(3, dev->mmio + LinePolarities); - writeb(0xc0, dev->mmio + AckSer); + writeb(0, dev->mmio + OP_MODE); + writeb(0x00, dev->mmio + CLOCK_REG); + writeb(1, dev->mmio + SEQUENCE); + writeb(0x04, dev->mmio + REQ_REG); + writeb(4, dev->mmio + BLOCK_MODE); + writeb(3, dev->mmio + LINE_POLARITIES); + writeb(0xc0, dev->mmio + ACK_SER); writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg, CMDF_ROUND_NEAREST), - dev->mmio + StartDelay); - writeb(1, dev->mmio + ReqDelay); - writeb(1, dev->mmio + ReqNotDelay); - writeb(1, dev->mmio + AckDelay); - writeb(0x0b, dev->mmio + AckNotDelay); - writeb(0x01, dev->mmio + Data1Delay); + dev->mmio + START_DELAY); + writeb(1, dev->mmio + REQ_DELAY); + writeb(1, dev->mmio + REQ_NOT_DELAY); + writeb(1, dev->mmio + ACK_DELAY); + writeb(0x0b, dev->mmio + ACK_NOT_DELAY); + writeb(0x01, dev->mmio + DATA_1_DELAY); /* * manual, page 4-5: - * ClockSpeed comment is incorrectly listed on DAQOptions + * CLOCK_SPEED comment is incorrectly listed on DAQ_OPTIONS */ - writew(0, dev->mmio + ClockSpeed); - writeb(0, dev->mmio + DAQOptions); + writew(0, dev->mmio + CLOCK_SPEED); + writeb(0, dev->mmio + DAQ_OPTIONS); } else { /* TRIG_EXT */ /* page 4-5, "input with external REQs" */ - writeb(0, dev->mmio + OpMode); - writeb(0x00, dev->mmio + ClockReg); - writeb(0, dev->mmio + Sequence); - writeb(0x00, dev->mmio + ReqReg); - writeb(4, dev->mmio + BlockMode); + writeb(0, dev->mmio + OP_MODE); + writeb(0x00, dev->mmio + CLOCK_REG); + writeb(0, dev->mmio + SEQUENCE); + writeb(0x00, dev->mmio + REQ_REG); + writeb(4, dev->mmio + BLOCK_MODE); if (!(cmd->scan_begin_arg & CR_INVERT)) /* Leading Edge */ - writeb(0, dev->mmio + LinePolarities); + writeb(0, dev->mmio + LINE_POLARITIES); else /* Trailing Edge */ - writeb(2, dev->mmio + LinePolarities); - writeb(0x00, dev->mmio + AckSer); - writel(1, dev->mmio + StartDelay); - writeb(1, dev->mmio + ReqDelay); - writeb(1, dev->mmio + ReqNotDelay); - writeb(1, dev->mmio + AckDelay); - writeb(0x0C, dev->mmio + AckNotDelay); - writeb(0x10, dev->mmio + Data1Delay); - writew(0, dev->mmio + ClockSpeed); - writeb(0x60, dev->mmio + DAQOptions); + writeb(2, dev->mmio + LINE_POLARITIES); + writeb(0x00, dev->mmio + ACK_SER); + writel(1, dev->mmio + START_DELAY); + writeb(1, dev->mmio + REQ_DELAY); + writeb(1, dev->mmio + REQ_NOT_DELAY); + writeb(1, dev->mmio + ACK_DELAY); + writeb(0x0C, dev->mmio + ACK_NOT_DELAY); + writeb(0x10, dev->mmio + DATA_1_DELAY); + writew(0, dev->mmio + CLOCK_SPEED); + writeb(0x60, dev->mmio + DAQ_OPTIONS); } if (cmd->stop_src == TRIG_COUNT) { writel(cmd->stop_arg, - dev->mmio + Transfer_Count); + dev->mmio + TRANSFER_COUNT); } else { /* XXX */ } #ifdef USE_DMA - writeb(ClearPrimaryTC | ClearSecondaryTC, - dev->mmio + Group_1_First_Clear); + writeb(CLEAR_PRIMARY_TC | CLEAR_SECONDARY_TC, + dev->mmio + GROUP_1_FIRST_CLEAR); { int retval = setup_mite_dma(dev, s); @@ -701,25 +703,25 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return retval; } #else - writeb(0x00, dev->mmio + DMA_Line_Control_Group1); + writeb(0x00, dev->mmio + DMA_LINE_CONTROL_GROUP1); #endif - writeb(0x00, dev->mmio + DMA_Line_Control_Group2); + writeb(0x00, dev->mmio + DMA_LINE_CONTROL_GROUP2); /* clear and enable interrupts */ - writeb(0xff, dev->mmio + Group_1_First_Clear); - /* writeb(ClearExpired, dev->mmio+Group_1_Second_Clear); */ + writeb(0xff, dev->mmio + GROUP_1_FIRST_CLEAR); + /* writeb(CLEAR_EXPIRED, dev->mmio+GROUP_1_SECOND_CLEAR); */ - writeb(IntEn, dev->mmio + Interrupt_Control); - writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control); + writeb(INT_EN, dev->mmio + INTERRUPT_CONTROL); + writeb(0x03, dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL); if (cmd->stop_src == TRIG_NONE) { - devpriv->OpModeBits = DataLatching(0) | RunMode(7); + devpriv->OP_MODEBits = DATA_LATCHING(0) | RUN_MODE(7); } else { /* TRIG_TIMER */ - devpriv->OpModeBits = Numbered | RunMode(7); + devpriv->OP_MODEBits = NUMBERED | RUN_MODE(7); } if (cmd->start_src == TRIG_NOW) { /* start */ - writeb(devpriv->OpModeBits, dev->mmio + OpMode); + writeb(devpriv->OP_MODEBits, dev->mmio + OP_MODE); s->async->inttrig = NULL; } else { /* TRIG_INT */ @@ -732,7 +734,7 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int ni_pcidio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - writeb(0x00, dev->mmio + Master_DMA_And_Interrupt_Control); + writeb(0x00, dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL); ni_pcidio_release_di_mite_channel(dev); return 0; @@ -869,12 +871,12 @@ static int pci_6534_upload_firmware(struct comedi_device *dev) static void nidio_reset_board(struct comedi_device *dev) { - writel(0, dev->mmio + Port_IO(0)); - writel(0, dev->mmio + Port_Pin_Directions(0)); - writel(0, dev->mmio + Port_Pin_Mask(0)); + writel(0, dev->mmio + PORT_IO(0)); + writel(0, dev->mmio + PORT_PIN_DIRECTIONS(0)); + writel(0, dev->mmio + PORT_PIN_MASK(0)); /* disable interrupts on board */ - writeb(0, dev->mmio + Master_DMA_And_Interrupt_Control); + writeb(0, dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL); } static int nidio_auto_attach(struct comedi_device *dev, @@ -925,7 +927,7 @@ static int nidio_auto_attach(struct comedi_device *dev, return ret; dev_info(dev->class_dev, "%s rev=%d\n", dev->board_name, - readb(dev->mmio + Chip_Version)); + readb(dev->mmio + CHIP_VERSION)); s = &dev->subdevices[0]; -- cgit From d2c255be37f46b7d484783b556f280d2da3aecf8 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 9 Jan 2019 12:06:41 +0000 Subject: staging: wilc1000: remove set but not used variable 'msa' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/wilc1000/host_interface.c: In function 'wilc_parse_network_info': drivers/staging/wilc1000/host_interface.c:748:16: warning: variable 'msa' set but not used [-Wunused-but-set-variable] Signed-off-by: YueHaibing 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 5dae6e7155d3..c05c120fafc7 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -745,7 +745,7 @@ static s32 wilc_parse_network_info(u8 *msg_buffer, { struct network_info *info; struct ieee80211_mgmt *mgt; - u8 *wid_val, *msa, *ies; + u8 *wid_val, *ies; u16 wid_len, rx_len, ies_len; u8 msg_type; size_t offset; @@ -764,7 +764,6 @@ static s32 wilc_parse_network_info(u8 *msg_buffer, info->rssi = wid_val[0]; - msa = &wid_val[1]; mgt = (struct ieee80211_mgmt *)&wid_val[1]; rx_len = wid_len - 1; -- cgit From d94e038910a8ffd6b219e0ba6359dede951dc27e Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 22 Dec 2018 10:24:53 +0100 Subject: staging: goldfish: remove GPL boiler plate text The SPDX identifier is a legally binding shorthand, which can be used instead of the full boiler plate text. There is a SPDX identifier line in goldfish_audio.c. Remove the GPL boiler plate text to reduce file size. Signed-off-by: Michael Straube Signed-off-by: Greg Kroah-Hartman --- drivers/staging/goldfish/goldfish_audio.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c index d4520490cf6d..24a738238f9f 100644 --- a/drivers/staging/goldfish/goldfish_audio.c +++ b/drivers/staging/goldfish/goldfish_audio.c @@ -4,16 +4,6 @@ * * Copyright (C) 2007 Google, Inc. * Copyright (C) 2012 Intel, 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 -- cgit From 01ad0d0b15a968decb171b9bda8e5e4999d628fa Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 22 Dec 2018 10:46:23 +0100 Subject: staging: gs_fpgaboot: add SPDX identifiers This satisfies a checkpatch warning and is the preferred method for notating the license. The SPDX identifier is a legally binding shorthand, which can be used instead of the full boiler plate text. Signed-off-by: Michael Straube Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gs_fpgaboot/gs_fpgaboot.c | 12 +----------- drivers/staging/gs_fpgaboot/gs_fpgaboot.h | 12 +----------- drivers/staging/gs_fpgaboot/io.c | 13 +------------ drivers/staging/gs_fpgaboot/io.h | 12 +----------- 4 files changed, 4 insertions(+), 45 deletions(-) diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c index fa8b27e091a2..3e154562c64d 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c @@ -1,14 +1,4 @@ -/* - * 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. - */ +// SPDX-License-Identifier: GPL-2.0+ #include #include diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h index 986e841f6b5e..5cf12c14cca4 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.h +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.h @@ -1,14 +1,4 @@ -/* - * 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. - */ +/* SPDX-License-Identifier: GPL-2.0+ */ #include diff --git a/drivers/staging/gs_fpgaboot/io.c b/drivers/staging/gs_fpgaboot/io.c index 83a13ca7259a..3d17ca557611 100644 --- a/drivers/staging/gs_fpgaboot/io.c +++ b/drivers/staging/gs_fpgaboot/io.c @@ -1,15 +1,4 @@ -/* - * 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. - */ +// SPDX-License-Identifier: GPL-2.0+ #include #include diff --git a/drivers/staging/gs_fpgaboot/io.h b/drivers/staging/gs_fpgaboot/io.h index bc5d99cbda8f..9bd86a92e90f 100644 --- a/drivers/staging/gs_fpgaboot/io.h +++ b/drivers/staging/gs_fpgaboot/io.h @@ -1,14 +1,4 @@ -/* - * 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. - */ +/* SPDX-License-Identifier: GPL-2.0+ */ #define GPDIR 0 #define GPCFG 4 /* open drain or not */ -- cgit From e4abc2488073a1e2764313feac5312622c7f04f9 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 22 Dec 2018 10:46:24 +0100 Subject: staging: gs_fpgaboot: cleanup alignment issue - style Cleanup alignment issue reported by checkpatch. CHECK: Alignment should match open parenthesis Signed-off-by: Michael Straube Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gs_fpgaboot/io.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/gs_fpgaboot/io.c b/drivers/staging/gs_fpgaboot/io.c index 3d17ca557611..80903ec36b76 100644 --- a/drivers/staging/gs_fpgaboot/io.c +++ b/drivers/staging/gs_fpgaboot/io.c @@ -39,8 +39,7 @@ int xl_supported_prog_bus_width(enum wbus bus_bytes) case bus_2byte: break; default: - pr_err("unsupported program bus width %d\n", - bus_bytes); + pr_err("unsupported program bus width %d\n", bus_bytes); return 0; } -- cgit From 0a54ea9f481f1a2ca5a171e91ddaacb75040f287 Mon Sep 17 00:00:00 2001 From: Kangjie Lu Date: Sat, 22 Dec 2018 16:58:06 -0600 Subject: staging: rtlwifi: rtl8822b: fix a missing check of alloc_skb __netdev_alloc_skb() return NULl when it fails. skb_put() further uses it even when the allocation fails, leading to NULL pointer dereference. The fix inserts a check for the return value of __netdev_alloc_skb(). Signed-off-by: Kangjie Lu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtlwifi/rtl8822be/fw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/rtlwifi/rtl8822be/fw.c b/drivers/staging/rtlwifi/rtl8822be/fw.c index a40396614814..f061dd1382aa 100644 --- a/drivers/staging/rtlwifi/rtl8822be/fw.c +++ b/drivers/staging/rtlwifi/rtl8822be/fw.c @@ -486,6 +486,8 @@ bool rtl8822b_halmac_cb_write_data_h2c(struct rtl_priv *rtlpriv, u8 *buf, /* without GFP_DMA, pci_map_single() may not work */ skb = __netdev_alloc_skb(NULL, size, GFP_ATOMIC | GFP_DMA); + if (!skb) + return false; memcpy((u8 *)skb_put(skb, size), buf, size); return _rtl8822be_send_bcn_or_cmd_packet(rtlpriv->hw, skb, H2C_QUEUE); -- cgit From 7c106cbb2ba8c86bedd2868b690aee8965476b3b Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Mon, 7 Jan 2019 20:31:43 +0100 Subject: staging: mt7621-pci: use PCI definitions instead of hardcode values Seting up ports to enable PCI_COMMAND_MASTER is using '0x4' as a hardcore value and '0x4' also for PCI_COMMAND register instead of use definitions from linux pci system headers. Replace both. Signed-off-by: Sergio Paracuellos Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mt7621-pci/pci-mt7621.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c index 8db94fdbdd6d..507b8c68d20b 100644 --- a/drivers/staging/mt7621-pci/pci-mt7621.c +++ b/drivers/staging/mt7621-pci/pci-mt7621.c @@ -515,8 +515,9 @@ static void mt7621_pcie_enable_ports(struct mt7621_pcie *pcie) } for (slot = 0; slot < num_slots_enabled; slot++) { - val = read_config(pcie, slot, 0x4); - write_config(pcie, slot, 0x4, val | 0x4); + val = read_config(pcie, slot, PCI_COMMAND); + val |= PCI_COMMAND_MASTER; + write_config(pcie, slot, PCI_COMMAND, val); /* configure RC FTS number to 250 when it leaves L0s */ val = read_config(pcie, slot, PCIE_FTS_NUM); val &= ~PCIE_FTS_NUM_MASK; -- cgit From 41be1dc75efb81bf3cfb9838998166ce1104e7f3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 7 Jan 2019 23:11:30 +0000 Subject: staging: rtl8712: clean up various indentation and coding style issues There are several statements that are indented incorrectly so fix these. Also remove unnecessary { } braces and clean up a comment. Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/ieee80211.c | 2 +- drivers/staging/rtl8712/rtl8712_led.c | 6 +++--- drivers/staging/rtl8712/rtl871x_mlme.c | 2 +- drivers/staging/rtl8712/rtl871x_recv.c | 4 ++-- drivers/staging/rtl8712/rtl871x_sta_mgt.c | 2 +- drivers/staging/rtl8712/rtl871x_xmit.c | 8 ++++---- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c index bb4f56a5fb01..2eae11dd6b42 100644 --- a/drivers/staging/rtl8712/ieee80211.c +++ b/drivers/staging/rtl8712/ieee80211.c @@ -408,7 +408,7 @@ int r8712_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen) match = true; break; } - cnt += in_ie[cnt + 1] + 2; /* goto next */ + cnt += in_ie[cnt + 1] + 2; /* goto next */ } return match; } diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c index 5b1004b2df47..07fcf9b9b811 100644 --- a/drivers/staging/rtl8712/rtl8712_led.c +++ b/drivers/staging/rtl8712/rtl8712_led.c @@ -939,7 +939,7 @@ static void SwLedControlMode1(struct _adapter *padapter, } if (pLed->bLedLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); - pLed->bLedLinkBlinkInProgress = false; + pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); @@ -991,7 +991,7 @@ static void SwLedControlMode1(struct _adapter *padapter, } if (pLed->bLedLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); - pLed->bLedLinkBlinkInProgress = false; + pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); @@ -1018,7 +1018,7 @@ static void SwLedControlMode1(struct _adapter *padapter, } if (pLed->bLedLinkBlinkInProgress) { del_timer(&pLed->BlinkTimer); - pLed->bLedLinkBlinkInProgress = false; + pLed->bLedLinkBlinkInProgress = false; } if (pLed->bLedBlinkInProgress) { del_timer(&pLed->BlinkTimer); diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index 986a1d526918..3f17ef6f7e39 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -259,7 +259,7 @@ int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork) static int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst) { - u16 s_cap, d_cap; + u16 s_cap, d_cap; memcpy((u8 *)&s_cap, r8712_get_capability_from_ie(src->IEs), 2); memcpy((u8 *)&d_cap, r8712_get_capability_from_ie(dst->IEs), 2); diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index f10896df094b..0271ccf25f25 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -54,7 +54,7 @@ sint _r8712_init_recv_priv(struct recv_priv *precvpriv, sint i; union recv_frame *precvframe; - memset((unsigned char *)precvpriv, 0, sizeof(struct recv_priv)); + memset((unsigned char *)precvpriv, 0, sizeof(struct recv_priv)); spin_lock_init(&precvpriv->lock); _init_queue(&precvpriv->free_recv_queue); _init_queue(&precvpriv->recv_pending_queue); @@ -325,7 +325,7 @@ static sint sta2sta_data_frame(struct _adapter *adapter, */ if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN)) return _FAIL; - sta_addr = pattrib->bssid; + sta_addr = pattrib->bssid; } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { if (bmcast) { /* For AP mode, if DA == MCAST, then BSSID should diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c index 9648ee15b40e..7c30b9e68e70 100644 --- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c +++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c @@ -25,7 +25,7 @@ static void _init_stainfo(struct sta_info *psta) { memset((u8 *)psta, 0, sizeof(struct sta_info)); - spin_lock_init(&psta->lock); + spin_lock_init(&psta->lock); INIT_LIST_HEAD(&psta->list); INIT_LIST_HEAD(&psta->hash_list); _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv); diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 5c7dc9c6f76b..7c8857409916 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -193,8 +193,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, pattrib->ether_type = ntohs(etherhdr.h_proto); -{ - /*If driver xmit ARP packet, driver can set ps mode to initial + /* + * If driver xmit ARP packet, driver can set ps mode to initial * setting. It stands for getting DHCP or fix IP. */ if (pattrib->ether_type == 0x0806) { @@ -206,7 +206,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, padapter->registrypriv.smart_ps); } } -} + memcpy(pattrib->dst, ðerhdr.h_dest, ETH_ALEN); memcpy(pattrib->src, ðerhdr.h_source, ETH_ALEN); pattrib->pctrl = 0; @@ -949,7 +949,7 @@ static void alloc_hwxmits(struct _adapter *padapter) pxmitpriv->vo_txqueue.head = 0; hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue; hwxmits[1] .sta_queue = &pxmitpriv->vo_pending; - pxmitpriv->vi_txqueue.head = 0; + pxmitpriv->vi_txqueue.head = 0; hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue; hwxmits[2] .sta_queue = &pxmitpriv->vi_pending; pxmitpriv->bk_txqueue.head = 0; -- cgit From e4441911d9694a177be30eb77adf54d511ae192f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 7 Jan 2019 23:22:49 +0000 Subject: staging: rtl8192e: fix various indentation issues There are several statements that have indentation issues, fix these. Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c | 8 ++++---- drivers/staging/rtl8192e/rtl8192e/rtl_core.c | 6 +++--- drivers/staging/rtl8192e/rtl8192e/rtl_dm.c | 2 +- drivers/staging/rtl8192e/rtl8192e/rtl_wx.c | 2 +- drivers/staging/rtl8192e/rtl819x_BAProc.c | 6 +++--- drivers/staging/rtl8192e/rtllib_crypt_tkip.c | 2 +- drivers/staging/rtl8192e/rtllib_rx.c | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index 1c6ed5b2a6f9..19bb04b3f097 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c @@ -660,9 +660,9 @@ static void _rtl92e_hwconfig(struct net_device *dev) case WIRELESS_MODE_AUTO: case WIRELESS_MODE_N_24G: regBwOpMode = BW_OPMODE_20MHZ; - regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | - RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; - regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | + RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; break; case WIRELESS_MODE_N_5G: regBwOpMode = BW_OPMODE_5G; @@ -961,7 +961,7 @@ static void _rtl92e_net_update(struct net_device *dev) net = &priv->rtllib->current_network; rtl92e_config_rate(dev, &rate_config); priv->dot11CurrentPreambleMode = PREAMBLE_AUTO; - priv->basic_rate = rate_config &= 0x15f; + priv->basic_rate = rate_config &= 0x15f; rtl92e_writew(dev, BSSIDR, *(u16 *)net->bssid); rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(net->bssid + 2)); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 96f265eee007..7031f6833b8b 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -436,7 +436,7 @@ static int _rtl92e_qos_handle_probe_response(struct r8192_priv *priv, network->qos_data.param_count)) { network->qos_data.old_param_count = network->qos_data.param_count; - priv->rtllib->wmm_acm = network->qos_data.wmm_acm; + priv->rtllib->wmm_acm = network->qos_data.wmm_acm; schedule_work(&priv->qos_activate); RT_TRACE(COMP_QOS, "QoS parameters change call qos_activate\n"); @@ -1573,7 +1573,7 @@ static void _rtl92e_free_rx_ring(struct net_device *dev) pci_unmap_single(priv->pdev, *((dma_addr_t *)skb->cb), priv->rxbuffersize, PCI_DMA_FROMDEVICE); - kfree_skb(skb); + kfree_skb(skb); } pci_free_consistent(priv->pdev, @@ -2515,7 +2515,7 @@ static int _rtl92e_pci_probe(struct pci_dev *pdev, if (dev_alloc_name(dev, ifname) < 0) { RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); - dev_alloc_name(dev, ifname); + dev_alloc_name(dev, ifname); } RT_TRACE(COMP_INIT, "Driver probe completed1\n"); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index 9bf95bd0ad13..157bcee34067 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c @@ -996,7 +996,7 @@ static void _rtl92e_dm_check_tx_power_tracking_tssi(struct net_device *dev) tx_power_track_counter++; - if (tx_power_track_counter >= 180) { + if (tx_power_track_counter >= 180) { schedule_delayed_work(&priv->txpower_tracking_wq, 0); tx_power_track_counter = 0; } diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c index b798cde0ce47..44e06cba7b7b 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c @@ -738,7 +738,7 @@ static int _rtl92e_wx_set_enc(struct net_device *dev, else if (wrqu->encoding.length == 0xd) { ieee->pairwise_key_type = KEY_TYPE_WEP104; - rtl92e_enable_hw_security_config(dev); + rtl92e_enable_hw_security_config(dev); rtl92e_set_key(dev, key_idx, key_idx, KEY_TYPE_WEP104, zero_addr[key_idx], 0, hwkey); rtl92e_set_swcam(dev, key_idx, key_idx, KEY_TYPE_WEP104, diff --git a/drivers/staging/rtl8192e/rtl819x_BAProc.c b/drivers/staging/rtl8192e/rtl819x_BAProc.c index 687dbb04ed2e..2d330d2bbf6d 100644 --- a/drivers/staging/rtl8192e/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192e/rtl819x_BAProc.c @@ -139,7 +139,7 @@ static struct sk_buff *rtllib_DELBA(struct rtllib_device *ieee, u8 *dst, { union delba_param_set DelbaParamSet; struct sk_buff *skb = NULL; - struct rtllib_hdr_3addr *Delba = NULL; + struct rtllib_hdr_3addr *Delba = NULL; u8 *tag = NULL; u16 len = 6 + ieee->tx_headroom; @@ -316,7 +316,7 @@ OnADDBAReq_Fail: int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb) { - struct rtllib_hdr_3addr *rsp = NULL; + struct rtllib_hdr_3addr *rsp = NULL; struct ba_record *pPendingBA, *pAdmittedBA; struct tx_ts_record *pTS = NULL; u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL; @@ -420,7 +420,7 @@ OnADDBARsp_Reject: int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb) { - struct rtllib_hdr_3addr *delba = NULL; + struct rtllib_hdr_3addr *delba = NULL; union delba_param_set *pDelBaParamSet = NULL; u8 *dst = NULL; diff --git a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c index f38f1f74fcd6..55da8c9dfe50 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c @@ -285,7 +285,7 @@ static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct rtllib_tkip_data *tkey = priv; - int len; + int len; u8 *pos; struct rtllib_hdr_4addr *hdr; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index fa580ce1cf43..501ded929329 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -913,7 +913,7 @@ static size_t rtllib_rx_get_hdrlen(struct rtllib_device *ieee, rx_stats->bContainHTC = true; } - if (RTLLIB_QOS_HAS_SEQ(fc)) + if (RTLLIB_QOS_HAS_SEQ(fc)) rx_stats->bIsQosData = true; return hdrlen; -- cgit From 3262af0024797b1945d94ff677e517769832d462 Mon Sep 17 00:00:00 2001 From: Himadri Pandya Date: Sat, 12 Jan 2019 22:21:48 -0800 Subject: staging: rtl8192e: rename ChannelPlan[] to channel_array[] - style Fix checkpatch.pl warning: CHECK: Avoid CamelCase: Signed-off-by: Himadri Pandya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/dot11d.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rtl8192e/dot11d.c b/drivers/staging/rtl8192e/dot11d.c index 687deac19796..9116d16857c2 100644 --- a/drivers/staging/rtl8192e/dot11d.c +++ b/drivers/staging/rtl8192e/dot11d.c @@ -19,7 +19,7 @@ struct channel_list { u8 Len; }; -static struct channel_list ChannelPlan[] = { +static struct channel_list channel_array[] = { {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 24}, {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, @@ -62,14 +62,14 @@ void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee) ieee->bGlobalDomain = false; - if (ChannelPlan[channel_plan].Len != 0) { + if (channel_array[channel_plan].Len != 0) { memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map)); - for (i = 0; i < ChannelPlan[channel_plan].Len; i++) { - if (ChannelPlan[channel_plan].channel[i] < min_chan || - ChannelPlan[channel_plan].channel[i] > max_chan) + for (i = 0; i < channel_array[channel_plan].Len; i++) { + if (channel_array[channel_plan].channel[i] < min_chan || + channel_array[channel_plan].channel[i] > max_chan) break; - GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan + GET_DOT11D_INFO(ieee)->channel_map[channel_array [channel_plan].channel[i]] = 1; } } -- cgit From 75752154039fa65844d529d188083cea9b3ca3e7 Mon Sep 17 00:00:00 2001 From: Himadri Pandya Date: Sat, 12 Jan 2019 22:21:49 -0800 Subject: staging: rtl8192e: rename Len to len - style Fix checkpatch.pl warning: CHECK: Avoid CamelCase: Signed-off-by: Himadri Pandya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/dot11d.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8192e/dot11d.c b/drivers/staging/rtl8192e/dot11d.c index 9116d16857c2..be9a21062a2e 100644 --- a/drivers/staging/rtl8192e/dot11d.c +++ b/drivers/staging/rtl8192e/dot11d.c @@ -16,7 +16,7 @@ struct channel_list { u8 channel[32]; - u8 Len; + u8 len; }; static struct channel_list channel_array[] = { @@ -62,10 +62,10 @@ void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee) ieee->bGlobalDomain = false; - if (channel_array[channel_plan].Len != 0) { + if (channel_array[channel_plan].len != 0) { memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map)); - for (i = 0; i < channel_array[channel_plan].Len; i++) { + for (i = 0; i < channel_array[channel_plan].len; i++) { if (channel_array[channel_plan].channel[i] < min_chan || channel_array[channel_plan].channel[i] > max_chan) break; -- cgit From 2b2bbb561f6de45a8d3155e197e46fa199451485 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Sun, 13 Jan 2019 19:02:53 +0800 Subject: staging: rtl8712u: Remove dummy reset-resume callback An USB wireless dongle uses rtl8712u stops working after system suspend/resume. When a USB device lost its power during suspend, the USB core knows the power was lost and a reset-resume or a re-probe is required. But rtl8712u provides a dummy reset-resume callback, which gets called and renders the device dead after resume. So remove the reset-resume call back, if power was lost during suspend, let the USB core unbind and probe the device to solve the issue. Signed-off-by: Kai-Heng Feng Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/usb_intf.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 92d75d7c51ae..9cf2a798cfca 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -232,13 +232,6 @@ static int r871x_resume(struct usb_interface *pusb_intf) rtl871x_intf_resume(padapter); return 0; } - -static int r871x_reset_resume(struct usb_interface *pusb_intf) -{ - /* dummy routine */ - return 0; -} - #endif static struct drv_priv drvpriv = { @@ -249,7 +242,6 @@ static struct drv_priv drvpriv = { #ifdef CONFIG_PM .r871xu_drv.suspend = r871x_suspend, .r871xu_drv.resume = r871x_resume, - .r871xu_drv.reset_resume = r871x_reset_resume, #endif }; -- cgit From ac544a459a95fbded20132cc58bb51663c98114c Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Sun, 13 Jan 2019 19:02:54 +0800 Subject: staging: rtl8712u: Fix suspend and resume callbacks When system resume and the rtl8712u dongle didn't lose its power, it doesn't work quite right: [ 146.844241] r8712u 2-3:1.0 wlp0s4f1u3: Unable to resume ... [ 154.029573] r8712u 2-3:1.0 wlp0s4f1u3: In r8711_wx_set_scan: bDriverStopped=1 The !netif_running() check in PM callbacks aren't correct because rtl8712u doesn't support runtime suspend, so the when the PM ops get called, it's system suspend or system resume, hence we want to "stop everthing" or "resume everything". The NULL check on pnetdev is also redundant, the only place pnetdev can become NULL is the disconnect callback, which is mutually exclusive to PM callbacks. This can make rtl8712u starts working after system resume. Signed-off-by: Kai-Heng Feng Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/usb_intf.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 9cf2a798cfca..005010de9997 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -196,10 +196,6 @@ static int r871x_suspend(struct usb_interface *pusb_intf, pm_message_t state) struct _adapter *padapter = netdev_priv(pnetdev); netdev_info(pnetdev, "Suspending...\n"); - if (!pnetdev || !netif_running(pnetdev)) { - netdev_info(pnetdev, "Unable to suspend\n"); - return 0; - } padapter->bSuspended = true; rtl871x_intf_stop(padapter); if (pnetdev->netdev_ops->ndo_stop) @@ -221,10 +217,6 @@ static int r871x_resume(struct usb_interface *pusb_intf) struct _adapter *padapter = netdev_priv(pnetdev); netdev_info(pnetdev, "Resuming...\n"); - if (!pnetdev || !netif_running(pnetdev)) { - netdev_info(pnetdev, "Unable to resume\n"); - return 0; - } netif_device_attach(pnetdev); if (pnetdev->netdev_ops->ndo_open) pnetdev->netdev_ops->ndo_open(pnetdev); -- cgit From e28dd69ee81be1ce44cc96a61a2172fc503944a4 Mon Sep 17 00:00:00 2001 From: Nishad Kamdar Date: Mon, 14 Jan 2019 20:26:16 +0530 Subject: staging: greybus: gpio: switch GPIO portions to use GPIOLIB_IRQCHIP Convert the GPIO driver to use the GPIO irqchip library GPIOLIB_IRQCHIP instead of reimplementing the same. Reviewed-by: Johan Hovold Signed-off-by: Nishad Kamdar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/Kconfig | 1 + drivers/staging/greybus/TODO | 2 - drivers/staging/greybus/gpio.c | 156 +++------------------------------------- 3 files changed, 11 insertions(+), 148 deletions(-) diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig index ab096bcef98c..b571e4e8060b 100644 --- a/drivers/staging/greybus/Kconfig +++ b/drivers/staging/greybus/Kconfig @@ -148,6 +148,7 @@ if GREYBUS_BRIDGED_PHY config GREYBUS_GPIO tristate "Greybus GPIO Bridged PHY driver" depends on GPIOLIB + select GPIOLIB_IRQCHIP ---help--- Select this option if you have a device that follows the Greybus GPIO Bridged PHY Class specification. diff --git a/drivers/staging/greybus/TODO b/drivers/staging/greybus/TODO index 3b90a5711998..31f1f2cb401c 100644 --- a/drivers/staging/greybus/TODO +++ b/drivers/staging/greybus/TODO @@ -1,5 +1,3 @@ * Convert all uses of the old GPIO API from to the GPIO descriptor API in and look up GPIO lines from device tree or ACPI. -* Convert the GPIO driver to use the GPIO irqchip library - GPIOLIB_IRQCHIP instead of reimplementing the same. diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index e110681e6f86..3151004d26fb 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -9,9 +9,9 @@ #include #include #include -#include #include #include +#include #include #include "greybus.h" @@ -39,11 +39,6 @@ struct gb_gpio_controller { struct gpio_chip chip; struct irq_chip irqc; - struct irq_chip *irqchip; - struct irq_domain *irqdomain; - unsigned int irq_base; - irq_flow_handler_t irq_handler; - unsigned int irq_default_type; struct mutex irq_lock; }; #define gpio_chip_to_gb_gpio_controller(chip) \ @@ -391,7 +386,7 @@ static int gb_gpio_request_handler(struct gb_operation *op) return -EINVAL; } - irq = irq_find_mapping(ggc->irqdomain, event->which); + irq = irq_find_mapping(ggc->chip.irq.domain, event->which); if (!irq) { dev_err(dev, "failed to find IRQ\n"); return -EINVAL; @@ -506,135 +501,6 @@ static int gb_gpio_controller_setup(struct gb_gpio_controller *ggc) return ret; } -/** - * gb_gpio_irq_map() - maps an IRQ into a GB gpio irqchip - * @d: the irqdomain used by this irqchip - * @irq: the global irq number used by this GB gpio irqchip irq - * @hwirq: the local IRQ/GPIO line offset on this GB gpio - * - * This function will set up the mapping for a certain IRQ line on a - * GB gpio by assigning the GB gpio as chip data, and using the irqchip - * stored inside the GB gpio. - */ -static int gb_gpio_irq_map(struct irq_domain *domain, unsigned int irq, - irq_hw_number_t hwirq) -{ - struct gpio_chip *chip = domain->host_data; - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); - - irq_set_chip_data(irq, ggc); - irq_set_chip_and_handler(irq, ggc->irqchip, ggc->irq_handler); - irq_set_noprobe(irq); - /* - * No set-up of the hardware will happen if IRQ_TYPE_NONE - * is passed as default type. - */ - if (ggc->irq_default_type != IRQ_TYPE_NONE) - irq_set_irq_type(irq, ggc->irq_default_type); - - return 0; -} - -static void gb_gpio_irq_unmap(struct irq_domain *d, unsigned int irq) -{ - irq_set_chip_and_handler(irq, NULL, NULL); - irq_set_chip_data(irq, NULL); -} - -static const struct irq_domain_ops gb_gpio_domain_ops = { - .map = gb_gpio_irq_map, - .unmap = gb_gpio_irq_unmap, -}; - -/** - * gb_gpio_irqchip_remove() - removes an irqchip added to a gb_gpio_controller - * @ggc: the gb_gpio_controller to remove the irqchip from - * - * This is called only from gb_gpio_remove() - */ -static void gb_gpio_irqchip_remove(struct gb_gpio_controller *ggc) -{ - unsigned int offset; - - /* Remove all IRQ mappings and delete the domain */ - if (ggc->irqdomain) { - for (offset = 0; offset < (ggc->line_max + 1); offset++) - irq_dispose_mapping(irq_find_mapping(ggc->irqdomain, - offset)); - irq_domain_remove(ggc->irqdomain); - } - - if (ggc->irqchip) - ggc->irqchip = NULL; -} - -/** - * gb_gpio_irqchip_add() - adds an irqchip to a gpio chip - * @chip: the gpio chip to add the irqchip to - * @irqchip: the irqchip to add to the adapter - * @first_irq: if not dynamically assigned, the base (first) IRQ to - * allocate gpio irqs from - * @handler: the irq handler to use (often a predefined irq core function) - * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE - * to have the core avoid setting up any default type in the hardware. - * - * This function closely associates a certain irqchip with a certain - * gpio chip, providing an irq domain to translate the local IRQs to - * global irqs, and making sure that the gpio chip - * is passed as chip data to all related functions. Driver callbacks - * need to use container_of() to get their local state containers back - * from the gpio chip passed as chip data. An irqdomain will be stored - * in the gpio chip that shall be used by the driver to handle IRQ number - * translation. The gpio chip will need to be initialized and registered - * before calling this function. - */ -static int gb_gpio_irqchip_add(struct gpio_chip *chip, - struct irq_chip *irqchip, - unsigned int first_irq, - irq_flow_handler_t handler, - unsigned int type) -{ - struct gb_gpio_controller *ggc; - unsigned int offset; - unsigned int irq_base; - - if (!chip || !irqchip) - return -EINVAL; - - ggc = gpio_chip_to_gb_gpio_controller(chip); - - ggc->irqchip = irqchip; - ggc->irq_handler = handler; - ggc->irq_default_type = type; - ggc->irqdomain = irq_domain_add_simple(NULL, - ggc->line_max + 1, first_irq, - &gb_gpio_domain_ops, chip); - if (!ggc->irqdomain) { - ggc->irqchip = NULL; - return -EINVAL; - } - - /* - * Prepare the mapping since the irqchip shall be orthogonal to - * any gpio calls. If the first_irq was zero, this is - * necessary to allocate descriptors for all IRQs. - */ - for (offset = 0; offset < (ggc->line_max + 1); offset++) { - irq_base = irq_create_mapping(ggc->irqdomain, offset); - if (offset == 0) - ggc->irq_base = irq_base; - } - - return 0; -} - -static int gb_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) -{ - struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip); - - return irq_find_mapping(ggc->irqdomain, offset); -} - static int gb_gpio_probe(struct gbphy_device *gbphy_dev, const struct gbphy_device_id *id) { @@ -694,7 +560,6 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev, gpio->get = gb_gpio_get; gpio->set = gb_gpio_set; gpio->set_config = gb_gpio_set_config; - gpio->to_irq = gb_gpio_to_irq; gpio->base = -1; /* Allocate base dynamically */ gpio->ngpio = ggc->line_max + 1; gpio->can_sleep = true; @@ -703,24 +568,24 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev, if (ret) goto exit_line_free; - ret = gb_gpio_irqchip_add(gpio, irqc, 0, - handle_level_irq, IRQ_TYPE_NONE); + ret = gpiochip_add(gpio); if (ret) { - dev_err(&gbphy_dev->dev, "failed to add irq chip: %d\n", ret); + dev_err(&gbphy_dev->dev, "failed to add gpio chip: %d\n", ret); goto exit_line_free; } - ret = gpiochip_add(gpio); + ret = gpiochip_irqchip_add(gpio, irqc, 0, handle_level_irq, + IRQ_TYPE_NONE); if (ret) { - dev_err(&gbphy_dev->dev, "failed to add gpio chip: %d\n", ret); - goto exit_gpio_irqchip_remove; + dev_err(&gbphy_dev->dev, "failed to add irq chip: %d\n", ret); + goto exit_gpiochip_remove; } gbphy_runtime_put_autosuspend(gbphy_dev); return 0; -exit_gpio_irqchip_remove: - gb_gpio_irqchip_remove(ggc); +exit_gpiochip_remove: + gpiochip_remove(gpio); exit_line_free: kfree(ggc->lines); exit_connection_disable: @@ -744,7 +609,6 @@ static void gb_gpio_remove(struct gbphy_device *gbphy_dev) gb_connection_disable_rx(connection); gpiochip_remove(&ggc->chip); - gb_gpio_irqchip_remove(ggc); gb_connection_disable(connection); gb_connection_destroy(connection); kfree(ggc->lines); -- cgit From fbacec8f2a0e05dd72de475224f3ab1c705c70fb Mon Sep 17 00:00:00 2001 From: Nishad Kamdar Date: Mon, 14 Jan 2019 20:27:31 +0530 Subject: staging: greybus: arche-apb-ctrl.c: Switch to the gpio descriptor interface Use the gpiod interface instead of the deprecated old non-descriptor interface while continuing to ignore gpio flags from device tree in functions "deassert_reset()" and "assert_reset()" for now. Reviewed-by: Johan Hovold Signed-off-by: Nishad Kamdar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/arche-apb-ctrl.c | 152 +++++++++++++------------------ 1 file changed, 61 insertions(+), 91 deletions(-) diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c index be5ffed90bcf..bbf3ba744fc4 100644 --- a/drivers/staging/greybus/arche-apb-ctrl.c +++ b/drivers/staging/greybus/arche-apb-ctrl.c @@ -8,9 +8,8 @@ #include #include -#include +#include #include -#include #include #include #include @@ -24,12 +23,12 @@ static void apb_bootret_deassert(struct device *dev); struct arche_apb_ctrl_drvdata { /* Control GPIO signals to and from AP <=> AP Bridges */ - int resetn_gpio; - int boot_ret_gpio; - int pwroff_gpio; - int wake_in_gpio; - int wake_out_gpio; - int pwrdn_gpio; + struct gpio_desc *resetn; + struct gpio_desc *boot_ret; + struct gpio_desc *pwroff; + struct gpio_desc *wake_in; + struct gpio_desc *wake_out; + struct gpio_desc *pwrdn; enum arche_platform_state state; bool init_disabled; @@ -37,28 +36,28 @@ struct arche_apb_ctrl_drvdata { struct regulator *vcore; struct regulator *vio; - int clk_en_gpio; + struct gpio_desc *clk_en; struct clk *clk; struct pinctrl *pinctrl; struct pinctrl_state *pin_default; /* V2: SPI Bus control */ - int spi_en_gpio; + struct gpio_desc *spi_en; bool spi_en_polarity_high; }; /* * Note that these low level api's are active high */ -static inline void deassert_reset(unsigned int gpio) +static inline void deassert_reset(struct gpio_desc *gpio) { - gpio_set_value(gpio, 1); + gpiod_set_raw_value(gpio, 1); } -static inline void assert_reset(unsigned int gpio) +static inline void assert_reset(struct gpio_desc *gpio) { - gpio_set_value(gpio, 0); + gpiod_set_raw_value(gpio, 0); } /* @@ -75,11 +74,10 @@ static int coldboot_seq(struct platform_device *pdev) return 0; /* Hold APB in reset state */ - assert_reset(apb->resetn_gpio); + assert_reset(apb->resetn); - if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && - gpio_is_valid(apb->spi_en_gpio)) - devm_gpio_free(dev, apb->spi_en_gpio); + if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en) + devm_gpiod_put(dev, apb->spi_en); /* Enable power to APB */ if (!IS_ERR(apb->vcore)) { @@ -101,13 +99,13 @@ static int coldboot_seq(struct platform_device *pdev) apb_bootret_deassert(dev); /* On DB3 clock was not mandatory */ - if (gpio_is_valid(apb->clk_en_gpio)) - gpio_set_value(apb->clk_en_gpio, 1); + if (apb->clk_en) + gpiod_set_value(apb->clk_en, 1); usleep_range(100, 200); /* deassert reset to APB : Active-low signal */ - deassert_reset(apb->resetn_gpio); + deassert_reset(apb->resetn); apb->state = ARCHE_PLATFORM_STATE_ACTIVE; @@ -136,25 +134,25 @@ static int fw_flashing_seq(struct platform_device *pdev) return ret; } - if (gpio_is_valid(apb->spi_en_gpio)) { + if (apb->spi_en) { unsigned long flags; if (apb->spi_en_polarity_high) - flags = GPIOF_OUT_INIT_HIGH; + flags = GPIOD_OUT_HIGH; else - flags = GPIOF_OUT_INIT_LOW; + flags = GPIOD_OUT_LOW; - ret = devm_gpio_request_one(dev, apb->spi_en_gpio, - flags, "apb_spi_en"); - if (ret) { - dev_err(dev, "Failed requesting SPI bus en gpio %d\n", - apb->spi_en_gpio); + apb->spi_en = devm_gpiod_get(dev, "spi-en", flags); + if (IS_ERR(apb->spi_en)) { + ret = PTR_ERR(apb->spi_en); + dev_err(dev, "Failed requesting SPI bus en GPIO: %d\n", + ret); return ret; } } /* for flashing device should be in reset state */ - assert_reset(apb->resetn_gpio); + assert_reset(apb->resetn); apb->state = ARCHE_PLATFORM_STATE_FW_FLASHING; return 0; @@ -176,9 +174,8 @@ static int standby_boot_seq(struct platform_device *pdev) apb->state == ARCHE_PLATFORM_STATE_OFF) return 0; - if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && - gpio_is_valid(apb->spi_en_gpio)) - devm_gpio_free(dev, apb->spi_en_gpio); + if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en) + devm_gpiod_put(dev, apb->spi_en); /* * As per WDM spec, do nothing @@ -201,13 +198,12 @@ static void poweroff_seq(struct platform_device *pdev) if (apb->init_disabled || apb->state == ARCHE_PLATFORM_STATE_OFF) return; - if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && - gpio_is_valid(apb->spi_en_gpio)) - devm_gpio_free(dev, apb->spi_en_gpio); + if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en) + devm_gpiod_put(dev, apb->spi_en); /* disable the clock */ - if (gpio_is_valid(apb->clk_en_gpio)) - gpio_set_value(apb->clk_en_gpio, 0); + if (apb->clk_en) + gpiod_set_value(apb->clk_en, 0); if (!IS_ERR(apb->vcore) && regulator_is_enabled(apb->vcore) > 0) regulator_disable(apb->vcore); @@ -216,7 +212,7 @@ static void poweroff_seq(struct platform_device *pdev) regulator_disable(apb->vio); /* As part of exit, put APB back in reset state */ - assert_reset(apb->resetn_gpio); + assert_reset(apb->resetn); apb->state = ARCHE_PLATFORM_STATE_OFF; /* TODO: May have to send an event to SVC about this exit */ @@ -226,7 +222,7 @@ static void apb_bootret_deassert(struct device *dev) { struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev); - gpio_set_value(apb->boot_ret_gpio, 0); + gpiod_set_value(apb->boot_ret, 0); } int apb_ctrl_coldboot(struct device *dev) @@ -322,66 +318,44 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, struct arche_apb_ctrl_drvdata *apb) { struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; int ret; - apb->resetn_gpio = of_get_named_gpio(np, "reset-gpios", 0); - if (apb->resetn_gpio < 0) { - dev_err(dev, "failed to get reset gpio\n"); - return apb->resetn_gpio; - } - ret = devm_gpio_request_one(dev, apb->resetn_gpio, - GPIOF_OUT_INIT_LOW, "apb-reset"); - if (ret) { - dev_err(dev, "Failed requesting reset gpio %d\n", - apb->resetn_gpio); + apb->resetn = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(apb->resetn)) { + ret = PTR_ERR(apb->resetn); + dev_err(dev, "Failed requesting reset GPIO: %d\n", ret); return ret; } - apb->boot_ret_gpio = of_get_named_gpio(np, "boot-ret-gpios", 0); - if (apb->boot_ret_gpio < 0) { - dev_err(dev, "failed to get boot retention gpio\n"); - return apb->boot_ret_gpio; - } - ret = devm_gpio_request_one(dev, apb->boot_ret_gpio, - GPIOF_OUT_INIT_LOW, "boot retention"); - if (ret) { - dev_err(dev, "Failed requesting bootret gpio %d\n", - apb->boot_ret_gpio); + apb->boot_ret = devm_gpiod_get(dev, "boot-ret", GPIOD_OUT_LOW); + if (IS_ERR(apb->boot_ret)) { + ret = PTR_ERR(apb->boot_ret); + dev_err(dev, "Failed requesting bootret GPIO: %d\n", ret); return ret; } /* It's not mandatory to support power management interface */ - apb->pwroff_gpio = of_get_named_gpio(np, "pwr-off-gpios", 0); - if (apb->pwroff_gpio < 0) { - dev_err(dev, "failed to get power off gpio\n"); - return apb->pwroff_gpio; - } - ret = devm_gpio_request_one(dev, apb->pwroff_gpio, - GPIOF_IN, "pwroff_n"); - if (ret) { - dev_err(dev, "Failed requesting pwroff_n gpio %d\n", - apb->pwroff_gpio); + apb->pwroff = devm_gpiod_get_optional(dev, "pwr-off", GPIOD_IN); + if (IS_ERR(apb->pwroff)) { + ret = PTR_ERR(apb->pwroff); + dev_err(dev, "Failed requesting pwroff_n GPIO: %d\n", ret); return ret; } /* Do not make clock mandatory as of now (for DB3) */ - apb->clk_en_gpio = of_get_named_gpio(np, "clock-en-gpio", 0); - if (apb->clk_en_gpio < 0) { - dev_warn(dev, "failed to get clock en gpio\n"); - } else if (gpio_is_valid(apb->clk_en_gpio)) { - ret = devm_gpio_request_one(dev, apb->clk_en_gpio, - GPIOF_OUT_INIT_LOW, "apb_clk_en"); - if (ret) { - dev_warn(dev, "Failed requesting APB clock en gpio %d\n", - apb->clk_en_gpio); - return ret; - } + apb->clk_en = devm_gpiod_get_optional(dev, "clock-en", GPIOD_OUT_LOW); + if (IS_ERR(apb->clk_en)) { + ret = PTR_ERR(apb->clk_en); + dev_err(dev, "Failed requesting APB clock en GPIO: %d\n", ret); + return ret; } - apb->pwrdn_gpio = of_get_named_gpio(np, "pwr-down-gpios", 0); - if (apb->pwrdn_gpio < 0) - dev_warn(dev, "failed to get power down gpio\n"); + apb->pwrdn = devm_gpiod_get(dev, "pwr-down", GPIOD_OUT_LOW); + if (IS_ERR(apb->pwrdn)) { + ret = PTR_ERR(apb->pwrdn); + dev_warn(dev, "Failed requesting power down GPIO: %d\n", ret); + return ret; + } /* Regulators are optional, as we may have fixed supply coming in */ apb->vcore = devm_regulator_get(dev, "vcore"); @@ -404,12 +378,8 @@ static int apb_ctrl_get_devtree_data(struct platform_device *pdev, } /* Only applicable for platform >= V2 */ - apb->spi_en_gpio = of_get_named_gpio(np, "spi-en-gpio", 0); - if (apb->spi_en_gpio >= 0) { - if (of_property_read_bool(pdev->dev.of_node, - "spi-en-active-high")) - apb->spi_en_polarity_high = true; - } + if (of_property_read_bool(pdev->dev.of_node, "gb,spi-en-active-high")) + apb->spi_en_polarity_high = true; return 0; } -- cgit From 4207b5870da5b79a7831cbead2cb60daeab7d64f Mon Sep 17 00:00:00 2001 From: Nishad Kamdar Date: Mon, 14 Jan 2019 20:28:59 +0530 Subject: staging: greybus: arche-platform: Switch to the gpio descriptor interface Use the gpiod interface instead of the deprecated old non-descriptor interface while continuing to ignore gpio flags from device tree in "svc_reset_onoff()" for now. Reviewed-by: Johan Hovold Signed-off-by: Nishad Kamdar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/arche-platform.c | 124 ++++++++++--------------------- 1 file changed, 41 insertions(+), 83 deletions(-) diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 4c36e88766e7..6eb842040c22 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -8,10 +8,9 @@ #include #include -#include +#include #include #include -#include #include #include #include @@ -45,14 +44,14 @@ enum svc_wakedetect_state { struct arche_platform_drvdata { /* Control GPIO signals to and from AP <=> SVC */ - int svc_reset_gpio; + struct gpio_desc *svc_reset; bool is_reset_act_hi; - int svc_sysboot_gpio; - int wake_detect_gpio; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */ + struct gpio_desc *svc_sysboot; + struct gpio_desc *wake_detect; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */ enum arche_platform_state state; - int svc_refclk_req; + struct gpio_desc *svc_refclk_req; struct clk *svc_ref_clk; struct pinctrl *pinctrl; @@ -85,9 +84,9 @@ static void arche_platform_set_wake_detect_state( arche_pdata->wake_detect_state = state; } -static inline void svc_reset_onoff(unsigned int gpio, bool onoff) +static inline void svc_reset_onoff(struct gpio_desc *gpio, bool onoff) { - gpio_set_value(gpio, onoff); + gpiod_set_raw_value(gpio, onoff); } static int apb_cold_boot(struct device *dev, void *data) @@ -116,7 +115,6 @@ static int apb_poweroff(struct device *dev, void *data) static void arche_platform_wd_irq_en(struct arche_platform_drvdata *arche_pdata) { /* Enable interrupt here, to read event back from SVC */ - gpio_direction_input(arche_pdata->wake_detect_gpio); enable_irq(arche_pdata->wake_detect_irq); } @@ -160,7 +158,7 @@ static irqreturn_t arche_platform_wd_irq(int irq, void *devid) spin_lock_irqsave(&arche_pdata->wake_lock, flags); - if (gpio_get_value(arche_pdata->wake_detect_gpio)) { + if (gpiod_get_value(arche_pdata->wake_detect)) { /* wake/detect rising */ /* @@ -224,10 +222,9 @@ arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata) dev_info(arche_pdata->dev, "Booting from cold boot state\n"); - svc_reset_onoff(arche_pdata->svc_reset_gpio, - arche_pdata->is_reset_act_hi); + svc_reset_onoff(arche_pdata->svc_reset, arche_pdata->is_reset_act_hi); - gpio_set_value(arche_pdata->svc_sysboot_gpio, 0); + gpiod_set_value(arche_pdata->svc_sysboot, 0); usleep_range(100, 200); ret = clk_prepare_enable(arche_pdata->svc_ref_clk); @@ -238,8 +235,7 @@ arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata) } /* bring SVC out of reset */ - svc_reset_onoff(arche_pdata->svc_reset_gpio, - !arche_pdata->is_reset_act_hi); + svc_reset_onoff(arche_pdata->svc_reset, !arche_pdata->is_reset_act_hi); arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_ACTIVE); @@ -259,10 +255,9 @@ arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata) dev_info(arche_pdata->dev, "Switching to FW flashing state\n"); - svc_reset_onoff(arche_pdata->svc_reset_gpio, - arche_pdata->is_reset_act_hi); + svc_reset_onoff(arche_pdata->svc_reset, arche_pdata->is_reset_act_hi); - gpio_set_value(arche_pdata->svc_sysboot_gpio, 1); + gpiod_set_value(arche_pdata->svc_sysboot, 1); usleep_range(100, 200); @@ -273,8 +268,7 @@ arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata) return ret; } - svc_reset_onoff(arche_pdata->svc_reset_gpio, - !arche_pdata->is_reset_act_hi); + svc_reset_onoff(arche_pdata->svc_reset, !arche_pdata->is_reset_act_hi); arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_FW_FLASHING); @@ -305,8 +299,7 @@ arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata) clk_disable_unprepare(arche_pdata->svc_ref_clk); /* As part of exit, put APB back in reset state */ - svc_reset_onoff(arche_pdata->svc_reset_gpio, - arche_pdata->is_reset_act_hi); + svc_reset_onoff(arche_pdata->svc_reset, arche_pdata->is_reset_act_hi); arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF); } @@ -435,6 +428,7 @@ static int arche_platform_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; int ret; + unsigned int flags; arche_pdata = devm_kzalloc(&pdev->dev, sizeof(*arche_pdata), GFP_KERNEL); @@ -444,61 +438,33 @@ static int arche_platform_probe(struct platform_device *pdev) /* setup svc reset gpio */ arche_pdata->is_reset_act_hi = of_property_read_bool(np, "svc,reset-active-high"); - arche_pdata->svc_reset_gpio = of_get_named_gpio(np, - "svc,reset-gpio", - 0); - if (!gpio_is_valid(arche_pdata->svc_reset_gpio)) { - dev_err(dev, "failed to get reset-gpio\n"); - return arche_pdata->svc_reset_gpio; - } - ret = devm_gpio_request(dev, arche_pdata->svc_reset_gpio, "svc-reset"); - if (ret) { - dev_err(dev, "failed to request svc-reset gpio:%d\n", ret); - return ret; - } - ret = gpio_direction_output(arche_pdata->svc_reset_gpio, - arche_pdata->is_reset_act_hi); - if (ret) { - dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); + if (arche_pdata->is_reset_act_hi) + flags = GPIOD_OUT_HIGH; + else + flags = GPIOD_OUT_LOW; + + arche_pdata->svc_reset = devm_gpiod_get(dev, "svc,reset", flags); + if (IS_ERR(arche_pdata->svc_reset)) { + ret = PTR_ERR(arche_pdata->svc_reset); + dev_err(dev, "failed to request svc-reset GPIO: %d\n", ret); return ret; } arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF); - arche_pdata->svc_sysboot_gpio = of_get_named_gpio(np, - "svc,sysboot-gpio", - 0); - if (!gpio_is_valid(arche_pdata->svc_sysboot_gpio)) { - dev_err(dev, "failed to get sysboot gpio\n"); - return arche_pdata->svc_sysboot_gpio; - } - ret = devm_gpio_request(dev, arche_pdata->svc_sysboot_gpio, "sysboot0"); - if (ret) { - dev_err(dev, "failed to request sysboot0 gpio:%d\n", ret); - return ret; - } - ret = gpio_direction_output(arche_pdata->svc_sysboot_gpio, 0); - if (ret) { - dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); + arche_pdata->svc_sysboot = devm_gpiod_get(dev, "svc,sysboot", + GPIOD_OUT_LOW); + if (IS_ERR(arche_pdata->svc_sysboot)) { + ret = PTR_ERR(arche_pdata->svc_sysboot); + dev_err(dev, "failed to request sysboot0 GPIO: %d\n", ret); return ret; } /* setup the clock request gpio first */ - arche_pdata->svc_refclk_req = of_get_named_gpio(np, - "svc,refclk-req-gpio", - 0); - if (!gpio_is_valid(arche_pdata->svc_refclk_req)) { - dev_err(dev, "failed to get svc clock-req gpio\n"); - return arche_pdata->svc_refclk_req; - } - ret = devm_gpio_request(dev, arche_pdata->svc_refclk_req, - "svc-clk-req"); - if (ret) { - dev_err(dev, "failed to request svc-clk-req gpio: %d\n", ret); - return ret; - } - ret = gpio_direction_input(arche_pdata->svc_refclk_req); - if (ret) { - dev_err(dev, "failed to set svc-clk-req gpio dir :%d\n", ret); + arche_pdata->svc_refclk_req = devm_gpiod_get(dev, "svc,refclk-req", + GPIOD_IN); + if (IS_ERR(arche_pdata->svc_refclk_req)) { + ret = PTR_ERR(arche_pdata->svc_refclk_req); + dev_err(dev, "failed to request svc-clk-req GPIO: %d\n", ret); return ret; } @@ -515,19 +481,11 @@ static int arche_platform_probe(struct platform_device *pdev) arche_pdata->num_apbs = of_get_child_count(np); dev_dbg(dev, "Number of APB's available - %d\n", arche_pdata->num_apbs); - arche_pdata->wake_detect_gpio = of_get_named_gpio(np, - "svc,wake-detect-gpio", - 0); - if (arche_pdata->wake_detect_gpio < 0) { - dev_err(dev, "failed to get wake detect gpio\n"); - return arche_pdata->wake_detect_gpio; - } - - ret = devm_gpio_request(dev, arche_pdata->wake_detect_gpio, - "wake detect"); - if (ret) { - dev_err(dev, "Failed requesting wake_detect gpio %d\n", - arche_pdata->wake_detect_gpio); + arche_pdata->wake_detect = devm_gpiod_get(dev, "svc,wake-detect", + GPIOD_IN); + if (IS_ERR(arche_pdata->wake_detect)) { + ret = PTR_ERR(arche_pdata->wake_detect); + dev_err(dev, "Failed requesting wake_detect GPIO: %d\n", ret); return ret; } @@ -538,7 +496,7 @@ static int arche_platform_probe(struct platform_device *pdev) spin_lock_init(&arche_pdata->wake_lock); mutex_init(&arche_pdata->platform_state_mutex); arche_pdata->wake_detect_irq = - gpio_to_irq(arche_pdata->wake_detect_gpio); + gpiod_to_irq(arche_pdata->wake_detect); ret = devm_request_threaded_irq(dev, arche_pdata->wake_detect_irq, arche_platform_wd_irq, -- cgit From e94e6d1454e4cd25c4482de89b0607580d82d625 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Tue, 15 Jan 2019 09:24:00 +0100 Subject: staging: rtl8188eu: remove unnecessary parentheses in os_intfs.c Remove unnecessary parentheses reported by checkpatch. Signed-off-by: Michael Straube Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/os_intfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index abcce2240f15..6681383579ee 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -198,8 +198,8 @@ static int rtw_net_set_mac_address(struct net_device *pnetdev, void *p) static struct net_device_stats *rtw_net_get_stats(struct net_device *pnetdev) { struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct recv_priv *precvpriv = &(padapter->recvpriv); + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct recv_priv *precvpriv = &padapter->recvpriv; padapter->stats.tx_packets = pxmitpriv->tx_pkts; padapter->stats.rx_packets = precvpriv->rx_pkts; -- cgit From 48101806c52203f64c6a76e74c1c68abd57903c2 Mon Sep 17 00:00:00 2001 From: Nishad Kamdar Date: Thu, 27 Dec 2018 22:51:29 +0530 Subject: Staging: emxx_udc: Switch to the gpio descriptor interface Convert VBUS GPIO to use GPIO descriptors from and stop using the old GPIO API. Signed-off-by: Nishad Kamdar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.c | 31 ++++++++++++++++--------------- drivers/staging/emxx_udc/emxx_udc.h | 2 ++ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index 8e8f57c4f029..a913d40f0801 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -27,7 +27,7 @@ #include #include -#include +#include #include "emxx_udc.h" @@ -2220,7 +2220,7 @@ static inline void _nbu2ss_check_vbus(struct nbu2ss_udc *udc) mdelay(VBUS_CHATTERING_MDELAY); /* wait (ms) */ /* VBUS ON Check*/ - reg_dt = gpio_get_value(VBUS_VALUE); + reg_dt = gpiod_get_value(vbus_gpio); if (reg_dt == 0) { udc->linux_suspended = 0; @@ -2247,7 +2247,7 @@ static inline void _nbu2ss_check_vbus(struct nbu2ss_udc *udc) } } else { mdelay(5); /* wait (5ms) */ - reg_dt = gpio_get_value(VBUS_VALUE); + reg_dt = gpiod_get_value(vbus_gpio); if (reg_dt == 0) return; @@ -2311,7 +2311,7 @@ static inline void _nbu2ss_int_usb_suspend(struct nbu2ss_udc *udc) u32 reg_dt; if (udc->usb_suspended == 0) { - reg_dt = gpio_get_value(VBUS_VALUE); + reg_dt = gpiod_get_value(vbus_gpio); if (reg_dt == 0) return; @@ -2351,7 +2351,7 @@ static irqreturn_t _nbu2ss_udc_irq(int irq, void *_udc) struct nbu2ss_udc *udc = (struct nbu2ss_udc *)_udc; struct fc_regs __iomem *preg = udc->p_regs; - if (gpio_get_value(VBUS_VALUE) == 0) { + if (gpiod_get_value(vbus_gpio) == 0) { _nbu2ss_writel(&preg->USB_INT_STA, ~USB_INT_STA_RW); _nbu2ss_writel(&preg->USB_INT_ENA, 0); return IRQ_HANDLED; @@ -2360,7 +2360,7 @@ static irqreturn_t _nbu2ss_udc_irq(int irq, void *_udc) spin_lock(&udc->lock); for (;;) { - if (gpio_get_value(VBUS_VALUE) == 0) { + if (gpiod_get_value(vbus_gpio) == 0) { _nbu2ss_writel(&preg->USB_INT_STA, ~USB_INT_STA_RW); _nbu2ss_writel(&preg->USB_INT_ENA, 0); status = 0; @@ -2750,7 +2750,7 @@ static int nbu2ss_ep_fifo_status(struct usb_ep *_ep) preg = udc->p_regs; - data = gpio_get_value(VBUS_VALUE); + data = gpiod_get_value(vbus_gpio); if (data == 0) return -EINVAL; @@ -2790,7 +2790,7 @@ static void nbu2ss_ep_fifo_flush(struct usb_ep *_ep) return; } - data = gpio_get_value(VBUS_VALUE); + data = gpiod_get_value(vbus_gpio); if (data == 0) return; @@ -2832,7 +2832,7 @@ static int nbu2ss_gad_get_frame(struct usb_gadget *pgadget) } udc = container_of(pgadget, struct nbu2ss_udc, gadget); - data = gpio_get_value(VBUS_VALUE); + data = gpiod_get_value(vbus_gpio); if (data == 0) return -EINVAL; @@ -2854,7 +2854,7 @@ static int nbu2ss_gad_wakeup(struct usb_gadget *pgadget) udc = container_of(pgadget, struct nbu2ss_udc, gadget); - data = gpio_get_value(VBUS_VALUE); + data = gpiod_get_value(vbus_gpio); if (data == 0) { dev_warn(&pgadget->dev, "VBUS LEVEL = %d\n", data); return -EINVAL; @@ -3119,12 +3119,13 @@ static int nbu2ss_drv_probe(struct platform_device *pdev) } /* VBUS Interrupt */ - irq_set_irq_type(INT_VBUS, IRQ_TYPE_EDGE_BOTH); - status = request_irq(INT_VBUS, + vbus_irq = gpiod_to_irq(vbus_gpio); + irq_set_irq_type(vbus_irq, IRQ_TYPE_EDGE_BOTH); + status = request_irq(vbus_irq, _nbu2ss_vbus_irq, IRQF_SHARED, driver_name, udc); if (status != 0) { - dev_err(udc->dev, "request_irq(INT_VBUS) failed\n"); + dev_err(udc->dev, "request_irq(vbus_irq) failed\n"); return status; } @@ -3160,7 +3161,7 @@ static int nbu2ss_drv_remove(struct platform_device *pdev) } /* Interrupt Handler - Release */ - free_irq(INT_VBUS, udc); + free_irq(vbus_irq, udc); return 0; } @@ -3201,7 +3202,7 @@ static int nbu2ss_drv_resume(struct platform_device *pdev) if (!udc) return 0; - data = gpio_get_value(VBUS_VALUE); + data = gpiod_get_value(vbus_gpio); if (data) { udc->vbus_active = 1; udc->devstate = USB_STATE_POWERED; diff --git a/drivers/staging/emxx_udc/emxx_udc.h b/drivers/staging/emxx_udc/emxx_udc.h index e28a74da9633..b8c3dee5626c 100644 --- a/drivers/staging/emxx_udc/emxx_udc.h +++ b/drivers/staging/emxx_udc/emxx_udc.h @@ -30,6 +30,8 @@ /* below hacked up for staging integration */ #define GPIO_VBUS 0 /* GPIO_P153 on KZM9D */ #define INT_VBUS 0 /* IRQ for GPIO_P153 */ +struct gpio_desc *vbus_gpio; +int vbus_irq; /*------------ Board dependence(Wait) */ -- cgit From d6b1090546450d9c34e64ed6f4cdbc6856db2f94 Mon Sep 17 00:00:00 2001 From: George Hilliard Date: Thu, 10 Jan 2019 17:43:36 -0700 Subject: staging: Move ralink-gdma to its own directory This is in preparation to allow it and the mt7621-dma drivers to be built separately. They are completely independent pieces of software, and the Kconfig specifies very different requirements. Cc: linux-kernel@vger.kernel.org Cc: devel@driverdev.osuosl.org Cc: Neil Brown Signed-off-by: George Hilliard Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/mt7621-dma/Kconfig | 6 - drivers/staging/mt7621-dma/Makefile | 1 - drivers/staging/mt7621-dma/ralink-gdma.c | 932 ------------------------------ drivers/staging/ralink-gdma/Kconfig | 6 + drivers/staging/ralink-gdma/Makefile | 3 + drivers/staging/ralink-gdma/ralink-gdma.c | 932 ++++++++++++++++++++++++++++++ 8 files changed, 944 insertions(+), 939 deletions(-) delete mode 100644 drivers/staging/mt7621-dma/ralink-gdma.c create mode 100644 drivers/staging/ralink-gdma/Kconfig create mode 100644 drivers/staging/ralink-gdma/Makefile create mode 100644 drivers/staging/ralink-gdma/ralink-gdma.c diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 4a3d6e00f7cb..46af55acda16 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -112,6 +112,8 @@ source "drivers/staging/mt7621-spi/Kconfig" source "drivers/staging/mt7621-dma/Kconfig" +source "drivers/staging/ralink-gdma/Kconfig" + source "drivers/staging/mt7621-mmc/Kconfig" source "drivers/staging/mt7621-eth/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 413890dd5a14..4d563ed0bc79 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_SOC_MT7621) += mt7621-pci-phy/ obj-$(CONFIG_SOC_MT7621) += mt7621-pinctrl/ obj-$(CONFIG_SOC_MT7621) += mt7621-spi/ obj-$(CONFIG_SOC_MT7621) += mt7621-dma/ +obj-$(CONFIG_SOC_MT7621) += ralink-gdma/ obj-$(CONFIG_SOC_MT7621) += mt7621-mmc/ obj-$(CONFIG_SOC_MT7621) += mt7621-eth/ obj-$(CONFIG_SOC_MT7621) += mt7621-dts/ diff --git a/drivers/staging/mt7621-dma/Kconfig b/drivers/staging/mt7621-dma/Kconfig index 2423c40099d1..b6e48a682c44 100644 --- a/drivers/staging/mt7621-dma/Kconfig +++ b/drivers/staging/mt7621-dma/Kconfig @@ -1,9 +1,3 @@ -config DMA_RALINK - tristate "RALINK DMA support" - depends on RALINK && !SOC_RT288X - select DMA_ENGINE - select DMA_VIRTUAL_CHANNELS - config MTK_HSDMA tristate "MTK HSDMA support" depends on RALINK && SOC_MT7621 diff --git a/drivers/staging/mt7621-dma/Makefile b/drivers/staging/mt7621-dma/Makefile index d3152d45cf45..c9e3e1619ab0 100644 --- a/drivers/staging/mt7621-dma/Makefile +++ b/drivers/staging/mt7621-dma/Makefile @@ -1,4 +1,3 @@ -obj-$(CONFIG_DMA_RALINK) += ralink-gdma.o obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o ccflags-y += -I$(srctree)/drivers/dma diff --git a/drivers/staging/mt7621-dma/ralink-gdma.c b/drivers/staging/mt7621-dma/ralink-gdma.c deleted file mode 100644 index d78042eba6dd..000000000000 --- a/drivers/staging/mt7621-dma/ralink-gdma.c +++ /dev/null @@ -1,932 +0,0 @@ -/* - * Copyright (C) 2013, Lars-Peter Clausen - * GDMA4740 DMAC support - * - * 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 "virt-dma.h" - -#define GDMA_REG_SRC_ADDR(x) (0x00 + (x) * 0x10) -#define GDMA_REG_DST_ADDR(x) (0x04 + (x) * 0x10) - -#define GDMA_REG_CTRL0(x) (0x08 + (x) * 0x10) -#define GDMA_REG_CTRL0_TX_MASK 0xffff -#define GDMA_REG_CTRL0_TX_SHIFT 16 -#define GDMA_REG_CTRL0_CURR_MASK 0xff -#define GDMA_REG_CTRL0_CURR_SHIFT 8 -#define GDMA_REG_CTRL0_SRC_ADDR_FIXED BIT(7) -#define GDMA_REG_CTRL0_DST_ADDR_FIXED BIT(6) -#define GDMA_REG_CTRL0_BURST_MASK 0x7 -#define GDMA_REG_CTRL0_BURST_SHIFT 3 -#define GDMA_REG_CTRL0_DONE_INT BIT(2) -#define GDMA_REG_CTRL0_ENABLE BIT(1) -#define GDMA_REG_CTRL0_SW_MODE BIT(0) - -#define GDMA_REG_CTRL1(x) (0x0c + (x) * 0x10) -#define GDMA_REG_CTRL1_SEG_MASK 0xf -#define GDMA_REG_CTRL1_SEG_SHIFT 22 -#define GDMA_REG_CTRL1_REQ_MASK 0x3f -#define GDMA_REG_CTRL1_SRC_REQ_SHIFT 16 -#define GDMA_REG_CTRL1_DST_REQ_SHIFT 8 -#define GDMA_REG_CTRL1_NEXT_MASK 0x1f -#define GDMA_REG_CTRL1_NEXT_SHIFT 3 -#define GDMA_REG_CTRL1_COHERENT BIT(2) -#define GDMA_REG_CTRL1_FAIL BIT(1) -#define GDMA_REG_CTRL1_MASK BIT(0) - -#define GDMA_REG_UNMASK_INT 0x200 -#define GDMA_REG_DONE_INT 0x204 - -#define GDMA_REG_GCT 0x220 -#define GDMA_REG_GCT_CHAN_MASK 0x3 -#define GDMA_REG_GCT_CHAN_SHIFT 3 -#define GDMA_REG_GCT_VER_MASK 0x3 -#define GDMA_REG_GCT_VER_SHIFT 1 -#define GDMA_REG_GCT_ARBIT_RR BIT(0) - -#define GDMA_REG_REQSTS 0x2a0 -#define GDMA_REG_ACKSTS 0x2a4 -#define GDMA_REG_FINSTS 0x2a8 - -/* for RT305X gdma registers */ -#define GDMA_RT305X_CTRL0_REQ_MASK 0xf -#define GDMA_RT305X_CTRL0_SRC_REQ_SHIFT 12 -#define GDMA_RT305X_CTRL0_DST_REQ_SHIFT 8 - -#define GDMA_RT305X_CTRL1_FAIL BIT(4) -#define GDMA_RT305X_CTRL1_NEXT_MASK 0x7 -#define GDMA_RT305X_CTRL1_NEXT_SHIFT 1 - -#define GDMA_RT305X_STATUS_INT 0x80 -#define GDMA_RT305X_STATUS_SIGNAL 0x84 -#define GDMA_RT305X_GCT 0x88 - -/* for MT7621 gdma registers */ -#define GDMA_REG_PERF_START(x) (0x230 + (x) * 0x8) -#define GDMA_REG_PERF_END(x) (0x234 + (x) * 0x8) - -enum gdma_dma_transfer_size { - GDMA_TRANSFER_SIZE_4BYTE = 0, - GDMA_TRANSFER_SIZE_8BYTE = 1, - GDMA_TRANSFER_SIZE_16BYTE = 2, - GDMA_TRANSFER_SIZE_32BYTE = 3, - GDMA_TRANSFER_SIZE_64BYTE = 4, -}; - -struct gdma_dma_sg { - dma_addr_t src_addr; - dma_addr_t dst_addr; - u32 len; -}; - -struct gdma_dma_desc { - struct virt_dma_desc vdesc; - - enum dma_transfer_direction direction; - bool cyclic; - - u32 residue; - unsigned int num_sgs; - struct gdma_dma_sg sg[]; -}; - -struct gdma_dmaengine_chan { - struct virt_dma_chan vchan; - unsigned int id; - unsigned int slave_id; - - dma_addr_t fifo_addr; - enum gdma_dma_transfer_size burst_size; - - struct gdma_dma_desc *desc; - unsigned int next_sg; -}; - -struct gdma_dma_dev { - struct dma_device ddev; - struct device_dma_parameters dma_parms; - struct gdma_data *data; - void __iomem *base; - struct tasklet_struct task; - volatile unsigned long chan_issued; - atomic_t cnt; - - struct gdma_dmaengine_chan chan[]; -}; - -struct gdma_data { - int chancnt; - u32 done_int_reg; - void (*init)(struct gdma_dma_dev *dma_dev); - int (*start_transfer)(struct gdma_dmaengine_chan *chan); -}; - -static struct gdma_dma_dev *gdma_dma_chan_get_dev( - struct gdma_dmaengine_chan *chan) -{ - return container_of(chan->vchan.chan.device, struct gdma_dma_dev, - ddev); -} - -static struct gdma_dmaengine_chan *to_gdma_dma_chan(struct dma_chan *c) -{ - return container_of(c, struct gdma_dmaengine_chan, vchan.chan); -} - -static struct gdma_dma_desc *to_gdma_dma_desc(struct virt_dma_desc *vdesc) -{ - return container_of(vdesc, struct gdma_dma_desc, vdesc); -} - -static inline uint32_t gdma_dma_read(struct gdma_dma_dev *dma_dev, - unsigned int reg) -{ - return readl(dma_dev->base + reg); -} - -static inline void gdma_dma_write(struct gdma_dma_dev *dma_dev, - unsigned reg, uint32_t val) -{ - writel(val, dma_dev->base + reg); -} - -static struct gdma_dma_desc *gdma_dma_alloc_desc(unsigned int num_sgs) -{ - return kzalloc(sizeof(struct gdma_dma_desc) + - sizeof(struct gdma_dma_sg) * num_sgs, GFP_ATOMIC); -} - -static enum gdma_dma_transfer_size gdma_dma_maxburst(u32 maxburst) -{ - if (maxburst < 2) - return GDMA_TRANSFER_SIZE_4BYTE; - else if (maxburst < 4) - return GDMA_TRANSFER_SIZE_8BYTE; - else if (maxburst < 8) - return GDMA_TRANSFER_SIZE_16BYTE; - else if (maxburst < 16) - return GDMA_TRANSFER_SIZE_32BYTE; - else - return GDMA_TRANSFER_SIZE_64BYTE; -} - -static int gdma_dma_config(struct dma_chan *c, - struct dma_slave_config *config) -{ - struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); - struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); - - if (config->device_fc) { - dev_err(dma_dev->ddev.dev, "not support flow controller\n"); - return -EINVAL; - } - - switch (config->direction) { - case DMA_MEM_TO_DEV: - if (config->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) { - dev_err(dma_dev->ddev.dev, "only support 4 byte buswidth\n"); - return -EINVAL; - } - chan->slave_id = config->slave_id; - chan->fifo_addr = config->dst_addr; - chan->burst_size = gdma_dma_maxburst(config->dst_maxburst); - break; - case DMA_DEV_TO_MEM: - if (config->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) { - dev_err(dma_dev->ddev.dev, "only support 4 byte buswidth\n"); - return -EINVAL; - } - chan->slave_id = config->slave_id; - chan->fifo_addr = config->src_addr; - chan->burst_size = gdma_dma_maxburst(config->src_maxburst); - break; - default: - dev_err(dma_dev->ddev.dev, "direction type %d error\n", - config->direction); - return -EINVAL; - } - - return 0; -} - -static int gdma_dma_terminate_all(struct dma_chan *c) -{ - struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); - struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); - unsigned long flags, timeout; - LIST_HEAD(head); - int i = 0; - - spin_lock_irqsave(&chan->vchan.lock, flags); - chan->desc = NULL; - clear_bit(chan->id, &dma_dev->chan_issued); - vchan_get_all_descriptors(&chan->vchan, &head); - spin_unlock_irqrestore(&chan->vchan.lock, flags); - - vchan_dma_desc_free_list(&chan->vchan, &head); - - /* wait dma transfer complete */ - timeout = jiffies + msecs_to_jiffies(5000); - while (gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)) & - GDMA_REG_CTRL0_ENABLE) { - if (time_after_eq(jiffies, timeout)) { - dev_err(dma_dev->ddev.dev, "chan %d wait timeout\n", - chan->id); - /* restore to init value */ - gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), 0); - break; - } - cpu_relax(); - i++; - } - - if (i) - dev_dbg(dma_dev->ddev.dev, "terminate chan %d loops %d\n", - chan->id, i); - - return 0; -} - -static void rt305x_dump_reg(struct gdma_dma_dev *dma_dev, int id) -{ - dev_dbg(dma_dev->ddev.dev, "chan %d, src %08x, dst %08x, ctr0 %08x, " \ - "ctr1 %08x, intr %08x, signal %08x\n", id, - gdma_dma_read(dma_dev, GDMA_REG_SRC_ADDR(id)), - gdma_dma_read(dma_dev, GDMA_REG_DST_ADDR(id)), - gdma_dma_read(dma_dev, GDMA_REG_CTRL0(id)), - gdma_dma_read(dma_dev, GDMA_REG_CTRL1(id)), - gdma_dma_read(dma_dev, GDMA_RT305X_STATUS_INT), - gdma_dma_read(dma_dev, GDMA_RT305X_STATUS_SIGNAL)); -} - -static int rt305x_gdma_start_transfer(struct gdma_dmaengine_chan *chan) -{ - struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); - dma_addr_t src_addr, dst_addr; - struct gdma_dma_sg *sg; - uint32_t ctrl0, ctrl1; - - /* verify chan is already stopped */ - ctrl0 = gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)); - if (unlikely(ctrl0 & GDMA_REG_CTRL0_ENABLE)) { - dev_err(dma_dev->ddev.dev, "chan %d is start(%08x).\n", - chan->id, ctrl0); - rt305x_dump_reg(dma_dev, chan->id); - return -EINVAL; - } - - sg = &chan->desc->sg[chan->next_sg]; - if (chan->desc->direction == DMA_MEM_TO_DEV) { - src_addr = sg->src_addr; - dst_addr = chan->fifo_addr; - ctrl0 = GDMA_REG_CTRL0_DST_ADDR_FIXED | \ - (8 << GDMA_RT305X_CTRL0_SRC_REQ_SHIFT) | \ - (chan->slave_id << GDMA_RT305X_CTRL0_DST_REQ_SHIFT); - } else if (chan->desc->direction == DMA_DEV_TO_MEM) { - src_addr = chan->fifo_addr; - dst_addr = sg->dst_addr; - ctrl0 = GDMA_REG_CTRL0_SRC_ADDR_FIXED | \ - (chan->slave_id << GDMA_RT305X_CTRL0_SRC_REQ_SHIFT) | \ - (8 << GDMA_RT305X_CTRL0_DST_REQ_SHIFT); - } else if (chan->desc->direction == DMA_MEM_TO_MEM) { - /* - * TODO: memcpy function have bugs. sometime it will copy - * more 8 bytes data when using dmatest verify. - */ - src_addr = sg->src_addr; - dst_addr = sg->dst_addr; - ctrl0 = GDMA_REG_CTRL0_SW_MODE | \ - (8 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ - (8 << GDMA_REG_CTRL1_DST_REQ_SHIFT); - } else { - dev_err(dma_dev->ddev.dev, "direction type %d error\n", - chan->desc->direction); - return -EINVAL; - } - - ctrl0 |= (sg->len << GDMA_REG_CTRL0_TX_SHIFT) | \ - (chan->burst_size << GDMA_REG_CTRL0_BURST_SHIFT) | \ - GDMA_REG_CTRL0_DONE_INT | GDMA_REG_CTRL0_ENABLE; - ctrl1 = chan->id << GDMA_REG_CTRL1_NEXT_SHIFT; - - chan->next_sg++; - gdma_dma_write(dma_dev, GDMA_REG_SRC_ADDR(chan->id), src_addr); - gdma_dma_write(dma_dev, GDMA_REG_DST_ADDR(chan->id), dst_addr); - gdma_dma_write(dma_dev, GDMA_REG_CTRL1(chan->id), ctrl1); - - /* make sure next_sg is update */ - wmb(); - gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), ctrl0); - - return 0; -} - -static void rt3883_dump_reg(struct gdma_dma_dev *dma_dev, int id) -{ - dev_dbg(dma_dev->ddev.dev, "chan %d, src %08x, dst %08x, ctr0 %08x, " \ - "ctr1 %08x, unmask %08x, done %08x, " \ - "req %08x, ack %08x, fin %08x\n", id, - gdma_dma_read(dma_dev, GDMA_REG_SRC_ADDR(id)), - gdma_dma_read(dma_dev, GDMA_REG_DST_ADDR(id)), - gdma_dma_read(dma_dev, GDMA_REG_CTRL0(id)), - gdma_dma_read(dma_dev, GDMA_REG_CTRL1(id)), - gdma_dma_read(dma_dev, GDMA_REG_UNMASK_INT), - gdma_dma_read(dma_dev, GDMA_REG_DONE_INT), - gdma_dma_read(dma_dev, GDMA_REG_REQSTS), - gdma_dma_read(dma_dev, GDMA_REG_ACKSTS), - gdma_dma_read(dma_dev, GDMA_REG_FINSTS)); -} - -static int rt3883_gdma_start_transfer(struct gdma_dmaengine_chan *chan) -{ - struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); - dma_addr_t src_addr, dst_addr; - struct gdma_dma_sg *sg; - uint32_t ctrl0, ctrl1; - - /* verify chan is already stopped */ - ctrl0 = gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)); - if (unlikely(ctrl0 & GDMA_REG_CTRL0_ENABLE)) { - dev_err(dma_dev->ddev.dev, "chan %d is start(%08x).\n", - chan->id, ctrl0); - rt3883_dump_reg(dma_dev, chan->id); - return -EINVAL; - } - - sg = &chan->desc->sg[chan->next_sg]; - if (chan->desc->direction == DMA_MEM_TO_DEV) { - src_addr = sg->src_addr; - dst_addr = chan->fifo_addr; - ctrl0 = GDMA_REG_CTRL0_DST_ADDR_FIXED; - ctrl1 = (32 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ - (chan->slave_id << GDMA_REG_CTRL1_DST_REQ_SHIFT); - } else if (chan->desc->direction == DMA_DEV_TO_MEM) { - src_addr = chan->fifo_addr; - dst_addr = sg->dst_addr; - ctrl0 = GDMA_REG_CTRL0_SRC_ADDR_FIXED; - ctrl1 = (chan->slave_id << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ - (32 << GDMA_REG_CTRL1_DST_REQ_SHIFT) | \ - GDMA_REG_CTRL1_COHERENT; - } else if (chan->desc->direction == DMA_MEM_TO_MEM) { - src_addr = sg->src_addr; - dst_addr = sg->dst_addr; - ctrl0 = GDMA_REG_CTRL0_SW_MODE; - ctrl1 = (32 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ - (32 << GDMA_REG_CTRL1_DST_REQ_SHIFT) | \ - GDMA_REG_CTRL1_COHERENT; - } else { - dev_err(dma_dev->ddev.dev, "direction type %d error\n", - chan->desc->direction); - return -EINVAL; - } - - ctrl0 |= (sg->len << GDMA_REG_CTRL0_TX_SHIFT) | \ - (chan->burst_size << GDMA_REG_CTRL0_BURST_SHIFT) | \ - GDMA_REG_CTRL0_DONE_INT | GDMA_REG_CTRL0_ENABLE; - ctrl1 |= chan->id << GDMA_REG_CTRL1_NEXT_SHIFT; - - chan->next_sg++; - gdma_dma_write(dma_dev, GDMA_REG_SRC_ADDR(chan->id), src_addr); - gdma_dma_write(dma_dev, GDMA_REG_DST_ADDR(chan->id), dst_addr); - gdma_dma_write(dma_dev, GDMA_REG_CTRL1(chan->id), ctrl1); - - /* make sure next_sg is update */ - wmb(); - gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), ctrl0); - - return 0; -} - -static inline int gdma_start_transfer(struct gdma_dma_dev *dma_dev, - struct gdma_dmaengine_chan *chan) -{ - return dma_dev->data->start_transfer(chan); -} - -static int gdma_next_desc(struct gdma_dmaengine_chan *chan) -{ - struct virt_dma_desc *vdesc; - - vdesc = vchan_next_desc(&chan->vchan); - if (!vdesc) { - chan->desc = NULL; - return 0; - } - chan->desc = to_gdma_dma_desc(vdesc); - chan->next_sg = 0; - - return 1; -} - -static void gdma_dma_chan_irq(struct gdma_dma_dev *dma_dev, - struct gdma_dmaengine_chan *chan) -{ - struct gdma_dma_desc *desc; - unsigned long flags; - int chan_issued; - - chan_issued = 0; - spin_lock_irqsave(&chan->vchan.lock, flags); - desc = chan->desc; - if (desc) { - if (desc->cyclic) { - vchan_cyclic_callback(&desc->vdesc); - if (chan->next_sg == desc->num_sgs) - chan->next_sg = 0; - chan_issued = 1; - } else { - desc->residue -= desc->sg[chan->next_sg - 1].len; - if (chan->next_sg == desc->num_sgs) { - list_del(&desc->vdesc.node); - vchan_cookie_complete(&desc->vdesc); - chan_issued = gdma_next_desc(chan); - } else { - chan_issued = 1; - } - } - } else { - dev_dbg(dma_dev->ddev.dev, "chan %d no desc to complete\n", - chan->id); - } - if (chan_issued) - set_bit(chan->id, &dma_dev->chan_issued); - spin_unlock_irqrestore(&chan->vchan.lock, flags); -} - -static irqreturn_t gdma_dma_irq(int irq, void *devid) -{ - struct gdma_dma_dev *dma_dev = devid; - u32 done, done_reg; - unsigned int i; - - done_reg = dma_dev->data->done_int_reg; - done = gdma_dma_read(dma_dev, done_reg); - if (unlikely(!done)) - return IRQ_NONE; - - /* clean done bits */ - gdma_dma_write(dma_dev, done_reg, done); - - i = 0; - while (done) { - if (done & 0x1) { - gdma_dma_chan_irq(dma_dev, &dma_dev->chan[i]); - atomic_dec(&dma_dev->cnt); - } - done >>= 1; - i++; - } - - /* start only have work to do */ - if (dma_dev->chan_issued) - tasklet_schedule(&dma_dev->task); - - return IRQ_HANDLED; -} - -static void gdma_dma_issue_pending(struct dma_chan *c) -{ - struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); - struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); - unsigned long flags; - - spin_lock_irqsave(&chan->vchan.lock, flags); - if (vchan_issue_pending(&chan->vchan) && !chan->desc) { - if (gdma_next_desc(chan)) { - set_bit(chan->id, &dma_dev->chan_issued); - tasklet_schedule(&dma_dev->task); - } else { - dev_dbg(dma_dev->ddev.dev, "chan %d no desc to issue\n", - chan->id); - } - } - spin_unlock_irqrestore(&chan->vchan.lock, flags); -} - -static struct dma_async_tx_descriptor *gdma_dma_prep_slave_sg( - struct dma_chan *c, struct scatterlist *sgl, - unsigned int sg_len, enum dma_transfer_direction direction, - unsigned long flags, void *context) -{ - struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); - struct gdma_dma_desc *desc; - struct scatterlist *sg; - unsigned int i; - - desc = gdma_dma_alloc_desc(sg_len); - if (!desc) { - dev_err(c->device->dev, "alloc sg decs error\n"); - return NULL; - } - desc->residue = 0; - - for_each_sg(sgl, sg, sg_len, i) { - if (direction == DMA_MEM_TO_DEV) { - desc->sg[i].src_addr = sg_dma_address(sg); - } else if (direction == DMA_DEV_TO_MEM) { - desc->sg[i].dst_addr = sg_dma_address(sg); - } else { - dev_err(c->device->dev, "direction type %d error\n", - direction); - goto free_desc; - } - - if (unlikely(sg_dma_len(sg) > GDMA_REG_CTRL0_TX_MASK)) { - dev_err(c->device->dev, "sg len too large %d\n", - sg_dma_len(sg)); - goto free_desc; - } - desc->sg[i].len = sg_dma_len(sg); - desc->residue += sg_dma_len(sg); - } - - desc->num_sgs = sg_len; - desc->direction = direction; - desc->cyclic = false; - - return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); - -free_desc: - kfree(desc); - return NULL; -} - -static struct dma_async_tx_descriptor *gdma_dma_prep_dma_memcpy( - struct dma_chan *c, dma_addr_t dest, dma_addr_t src, - size_t len, unsigned long flags) -{ - struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); - struct gdma_dma_desc *desc; - unsigned int num_periods, i; - size_t xfer_count; - - if (len <= 0) - return NULL; - - chan->burst_size = gdma_dma_maxburst(len >> 2); - - xfer_count = GDMA_REG_CTRL0_TX_MASK; - num_periods = DIV_ROUND_UP(len, xfer_count); - - desc = gdma_dma_alloc_desc(num_periods); - if (!desc) { - dev_err(c->device->dev, "alloc memcpy decs error\n"); - return NULL; - } - desc->residue = len; - - for (i = 0; i < num_periods; i++) { - desc->sg[i].src_addr = src; - desc->sg[i].dst_addr = dest; - if (len > xfer_count) - desc->sg[i].len = xfer_count; - else - desc->sg[i].len = len; - src += desc->sg[i].len; - dest += desc->sg[i].len; - len -= desc->sg[i].len; - } - - desc->num_sgs = num_periods; - desc->direction = DMA_MEM_TO_MEM; - desc->cyclic = false; - - return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); -} - -static struct dma_async_tx_descriptor *gdma_dma_prep_dma_cyclic( - struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len, - size_t period_len, enum dma_transfer_direction direction, - unsigned long flags) -{ - struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); - struct gdma_dma_desc *desc; - unsigned int num_periods, i; - - if (buf_len % period_len) - return NULL; - - if (period_len > GDMA_REG_CTRL0_TX_MASK) { - dev_err(c->device->dev, "cyclic len too large %d\n", - period_len); - return NULL; - } - - num_periods = buf_len / period_len; - desc = gdma_dma_alloc_desc(num_periods); - if (!desc) { - dev_err(c->device->dev, "alloc cyclic decs error\n"); - return NULL; - } - desc->residue = buf_len; - - for (i = 0; i < num_periods; i++) { - if (direction == DMA_MEM_TO_DEV) { - desc->sg[i].src_addr = buf_addr; - } else if (direction == DMA_DEV_TO_MEM) { - desc->sg[i].dst_addr = buf_addr; - } else { - dev_err(c->device->dev, "direction type %d error\n", - direction); - goto free_desc; - } - desc->sg[i].len = period_len; - buf_addr += period_len; - } - - desc->num_sgs = num_periods; - desc->direction = direction; - desc->cyclic = true; - - return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); - -free_desc: - kfree(desc); - return NULL; -} - -static enum dma_status gdma_dma_tx_status(struct dma_chan *c, - dma_cookie_t cookie, - struct dma_tx_state *state) -{ - struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); - struct virt_dma_desc *vdesc; - enum dma_status status; - unsigned long flags; - struct gdma_dma_desc *desc; - - status = dma_cookie_status(c, cookie, state); - if (status == DMA_COMPLETE || !state) - return status; - - spin_lock_irqsave(&chan->vchan.lock, flags); - desc = chan->desc; - if (desc && (cookie == desc->vdesc.tx.cookie)) { - /* - * We never update edesc->residue in the cyclic case, so we - * can tell the remaining room to the end of the circular - * buffer. - */ - if (desc->cyclic) - state->residue = desc->residue - - ((chan->next_sg - 1) * desc->sg[0].len); - else - state->residue = desc->residue; - } else { - vdesc = vchan_find_desc(&chan->vchan, cookie); - if (vdesc) - state->residue = to_gdma_dma_desc(vdesc)->residue; - } - spin_unlock_irqrestore(&chan->vchan.lock, flags); - - dev_dbg(c->device->dev, "tx residue %d bytes\n", state->residue); - - return status; -} - -static void gdma_dma_free_chan_resources(struct dma_chan *c) -{ - vchan_free_chan_resources(to_virt_chan(c)); -} - -static void gdma_dma_desc_free(struct virt_dma_desc *vdesc) -{ - kfree(container_of(vdesc, struct gdma_dma_desc, vdesc)); -} - -static void gdma_dma_tasklet(unsigned long arg) -{ - struct gdma_dma_dev *dma_dev = (struct gdma_dma_dev *)arg; - struct gdma_dmaengine_chan *chan; - static unsigned int last_chan; - unsigned int i, chan_mask; - - /* record last chan to round robin all chans */ - i = last_chan; - chan_mask = dma_dev->data->chancnt - 1; - do { - /* - * on mt7621. when verify with dmatest with all - * channel is enable. we need to limit only two - * channel is working at the same time. otherwise the - * data will have problem. - */ - if (atomic_read(&dma_dev->cnt) >= 2) { - last_chan = i; - break; - } - - if (test_and_clear_bit(i, &dma_dev->chan_issued)) { - chan = &dma_dev->chan[i]; - if (chan->desc) { - atomic_inc(&dma_dev->cnt); - gdma_start_transfer(dma_dev, chan); - } else { - dev_dbg(dma_dev->ddev.dev, "chan %d no desc to issue\n", chan->id); - } - if (!dma_dev->chan_issued) - break; - } - - i = (i + 1) & chan_mask; - } while (i != last_chan); -} - -static void rt305x_gdma_init(struct gdma_dma_dev *dma_dev) -{ - uint32_t gct; - - /* all chans round robin */ - gdma_dma_write(dma_dev, GDMA_RT305X_GCT, GDMA_REG_GCT_ARBIT_RR); - - gct = gdma_dma_read(dma_dev, GDMA_RT305X_GCT); - dev_info(dma_dev->ddev.dev, "revision: %d, channels: %d\n", - (gct >> GDMA_REG_GCT_VER_SHIFT) & GDMA_REG_GCT_VER_MASK, - 8 << ((gct >> GDMA_REG_GCT_CHAN_SHIFT) & - GDMA_REG_GCT_CHAN_MASK)); -} - -static void rt3883_gdma_init(struct gdma_dma_dev *dma_dev) -{ - uint32_t gct; - - /* all chans round robin */ - gdma_dma_write(dma_dev, GDMA_REG_GCT, GDMA_REG_GCT_ARBIT_RR); - - gct = gdma_dma_read(dma_dev, GDMA_REG_GCT); - dev_info(dma_dev->ddev.dev, "revision: %d, channels: %d\n", - (gct >> GDMA_REG_GCT_VER_SHIFT) & GDMA_REG_GCT_VER_MASK, - 8 << ((gct >> GDMA_REG_GCT_CHAN_SHIFT) & - GDMA_REG_GCT_CHAN_MASK)); -} - -static struct gdma_data rt305x_gdma_data = { - .chancnt = 8, - .done_int_reg = GDMA_RT305X_STATUS_INT, - .init = rt305x_gdma_init, - .start_transfer = rt305x_gdma_start_transfer, -}; - -static struct gdma_data rt3883_gdma_data = { - .chancnt = 16, - .done_int_reg = GDMA_REG_DONE_INT, - .init = rt3883_gdma_init, - .start_transfer = rt3883_gdma_start_transfer, -}; - -static const struct of_device_id gdma_of_match_table[] = { - { .compatible = "ralink,rt305x-gdma", .data = &rt305x_gdma_data }, - { .compatible = "ralink,rt3883-gdma", .data = &rt3883_gdma_data }, - { }, -}; - -static int gdma_dma_probe(struct platform_device *pdev) -{ - const struct of_device_id *match; - struct gdma_dmaengine_chan *chan; - struct gdma_dma_dev *dma_dev; - struct dma_device *dd; - unsigned int i; - struct resource *res; - int ret; - int irq; - void __iomem *base; - struct gdma_data *data; - - ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); - if (ret) - return ret; - - match = of_match_device(gdma_of_match_table, &pdev->dev); - if (!match) - return -EINVAL; - data = (struct gdma_data *) match->data; - - dma_dev = devm_kzalloc(&pdev->dev, - struct_size(dma_dev, chan, data->chancnt), - GFP_KERNEL); - if (!dma_dev) { - dev_err(&pdev->dev, "alloc dma device failed\n"); - return -EINVAL; - } - dma_dev->data = data; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(base)) - return PTR_ERR(base); - dma_dev->base = base; - tasklet_init(&dma_dev->task, gdma_dma_tasklet, (unsigned long)dma_dev); - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); - return -EINVAL; - } - ret = devm_request_irq(&pdev->dev, irq, gdma_dma_irq, - 0, dev_name(&pdev->dev), dma_dev); - if (ret) { - dev_err(&pdev->dev, "failed to request irq\n"); - return ret; - } - - device_reset(&pdev->dev); - - dd = &dma_dev->ddev; - dma_cap_set(DMA_MEMCPY, dd->cap_mask); - dma_cap_set(DMA_SLAVE, dd->cap_mask); - dma_cap_set(DMA_CYCLIC, dd->cap_mask); - dd->device_free_chan_resources = gdma_dma_free_chan_resources; - dd->device_prep_dma_memcpy = gdma_dma_prep_dma_memcpy; - dd->device_prep_slave_sg = gdma_dma_prep_slave_sg; - dd->device_prep_dma_cyclic = gdma_dma_prep_dma_cyclic; - dd->device_config = gdma_dma_config; - dd->device_terminate_all = gdma_dma_terminate_all; - dd->device_tx_status = gdma_dma_tx_status; - dd->device_issue_pending = gdma_dma_issue_pending; - - dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - dd->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); - dd->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; - - dd->dev = &pdev->dev; - dd->dev->dma_parms = &dma_dev->dma_parms; - dma_set_max_seg_size(dd->dev, GDMA_REG_CTRL0_TX_MASK); - INIT_LIST_HEAD(&dd->channels); - - for (i = 0; i < data->chancnt; i++) { - chan = &dma_dev->chan[i]; - chan->id = i; - chan->vchan.desc_free = gdma_dma_desc_free; - vchan_init(&chan->vchan, dd); - } - - /* init hardware */ - data->init(dma_dev); - - ret = dma_async_device_register(dd); - if (ret) { - dev_err(&pdev->dev, "failed to register dma device\n"); - return ret; - } - - ret = of_dma_controller_register(pdev->dev.of_node, - of_dma_xlate_by_chan_id, dma_dev); - if (ret) { - dev_err(&pdev->dev, "failed to register of dma controller\n"); - goto err_unregister; - } - - platform_set_drvdata(pdev, dma_dev); - - return 0; - -err_unregister: - dma_async_device_unregister(dd); - return ret; -} - -static int gdma_dma_remove(struct platform_device *pdev) -{ - struct gdma_dma_dev *dma_dev = platform_get_drvdata(pdev); - - tasklet_kill(&dma_dev->task); - of_dma_controller_free(pdev->dev.of_node); - dma_async_device_unregister(&dma_dev->ddev); - - return 0; -} - -static struct platform_driver gdma_dma_driver = { - .probe = gdma_dma_probe, - .remove = gdma_dma_remove, - .driver = { - .name = "gdma-rt2880", - .of_match_table = gdma_of_match_table, - }, -}; -module_platform_driver(gdma_dma_driver); - -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_DESCRIPTION("Ralink/MTK DMA driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/ralink-gdma/Kconfig b/drivers/staging/ralink-gdma/Kconfig new file mode 100644 index 000000000000..a12b2c672d48 --- /dev/null +++ b/drivers/staging/ralink-gdma/Kconfig @@ -0,0 +1,6 @@ +config DMA_RALINK + tristate "RALINK DMA support" + depends on RALINK && !SOC_RT288X + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + diff --git a/drivers/staging/ralink-gdma/Makefile b/drivers/staging/ralink-gdma/Makefile new file mode 100644 index 000000000000..5d917e0729bb --- /dev/null +++ b/drivers/staging/ralink-gdma/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_DMA_RALINK) += ralink-gdma.o + +ccflags-y += -I$(srctree)/drivers/dma diff --git a/drivers/staging/ralink-gdma/ralink-gdma.c b/drivers/staging/ralink-gdma/ralink-gdma.c new file mode 100644 index 000000000000..d78042eba6dd --- /dev/null +++ b/drivers/staging/ralink-gdma/ralink-gdma.c @@ -0,0 +1,932 @@ +/* + * Copyright (C) 2013, Lars-Peter Clausen + * GDMA4740 DMAC support + * + * 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 "virt-dma.h" + +#define GDMA_REG_SRC_ADDR(x) (0x00 + (x) * 0x10) +#define GDMA_REG_DST_ADDR(x) (0x04 + (x) * 0x10) + +#define GDMA_REG_CTRL0(x) (0x08 + (x) * 0x10) +#define GDMA_REG_CTRL0_TX_MASK 0xffff +#define GDMA_REG_CTRL0_TX_SHIFT 16 +#define GDMA_REG_CTRL0_CURR_MASK 0xff +#define GDMA_REG_CTRL0_CURR_SHIFT 8 +#define GDMA_REG_CTRL0_SRC_ADDR_FIXED BIT(7) +#define GDMA_REG_CTRL0_DST_ADDR_FIXED BIT(6) +#define GDMA_REG_CTRL0_BURST_MASK 0x7 +#define GDMA_REG_CTRL0_BURST_SHIFT 3 +#define GDMA_REG_CTRL0_DONE_INT BIT(2) +#define GDMA_REG_CTRL0_ENABLE BIT(1) +#define GDMA_REG_CTRL0_SW_MODE BIT(0) + +#define GDMA_REG_CTRL1(x) (0x0c + (x) * 0x10) +#define GDMA_REG_CTRL1_SEG_MASK 0xf +#define GDMA_REG_CTRL1_SEG_SHIFT 22 +#define GDMA_REG_CTRL1_REQ_MASK 0x3f +#define GDMA_REG_CTRL1_SRC_REQ_SHIFT 16 +#define GDMA_REG_CTRL1_DST_REQ_SHIFT 8 +#define GDMA_REG_CTRL1_NEXT_MASK 0x1f +#define GDMA_REG_CTRL1_NEXT_SHIFT 3 +#define GDMA_REG_CTRL1_COHERENT BIT(2) +#define GDMA_REG_CTRL1_FAIL BIT(1) +#define GDMA_REG_CTRL1_MASK BIT(0) + +#define GDMA_REG_UNMASK_INT 0x200 +#define GDMA_REG_DONE_INT 0x204 + +#define GDMA_REG_GCT 0x220 +#define GDMA_REG_GCT_CHAN_MASK 0x3 +#define GDMA_REG_GCT_CHAN_SHIFT 3 +#define GDMA_REG_GCT_VER_MASK 0x3 +#define GDMA_REG_GCT_VER_SHIFT 1 +#define GDMA_REG_GCT_ARBIT_RR BIT(0) + +#define GDMA_REG_REQSTS 0x2a0 +#define GDMA_REG_ACKSTS 0x2a4 +#define GDMA_REG_FINSTS 0x2a8 + +/* for RT305X gdma registers */ +#define GDMA_RT305X_CTRL0_REQ_MASK 0xf +#define GDMA_RT305X_CTRL0_SRC_REQ_SHIFT 12 +#define GDMA_RT305X_CTRL0_DST_REQ_SHIFT 8 + +#define GDMA_RT305X_CTRL1_FAIL BIT(4) +#define GDMA_RT305X_CTRL1_NEXT_MASK 0x7 +#define GDMA_RT305X_CTRL1_NEXT_SHIFT 1 + +#define GDMA_RT305X_STATUS_INT 0x80 +#define GDMA_RT305X_STATUS_SIGNAL 0x84 +#define GDMA_RT305X_GCT 0x88 + +/* for MT7621 gdma registers */ +#define GDMA_REG_PERF_START(x) (0x230 + (x) * 0x8) +#define GDMA_REG_PERF_END(x) (0x234 + (x) * 0x8) + +enum gdma_dma_transfer_size { + GDMA_TRANSFER_SIZE_4BYTE = 0, + GDMA_TRANSFER_SIZE_8BYTE = 1, + GDMA_TRANSFER_SIZE_16BYTE = 2, + GDMA_TRANSFER_SIZE_32BYTE = 3, + GDMA_TRANSFER_SIZE_64BYTE = 4, +}; + +struct gdma_dma_sg { + dma_addr_t src_addr; + dma_addr_t dst_addr; + u32 len; +}; + +struct gdma_dma_desc { + struct virt_dma_desc vdesc; + + enum dma_transfer_direction direction; + bool cyclic; + + u32 residue; + unsigned int num_sgs; + struct gdma_dma_sg sg[]; +}; + +struct gdma_dmaengine_chan { + struct virt_dma_chan vchan; + unsigned int id; + unsigned int slave_id; + + dma_addr_t fifo_addr; + enum gdma_dma_transfer_size burst_size; + + struct gdma_dma_desc *desc; + unsigned int next_sg; +}; + +struct gdma_dma_dev { + struct dma_device ddev; + struct device_dma_parameters dma_parms; + struct gdma_data *data; + void __iomem *base; + struct tasklet_struct task; + volatile unsigned long chan_issued; + atomic_t cnt; + + struct gdma_dmaengine_chan chan[]; +}; + +struct gdma_data { + int chancnt; + u32 done_int_reg; + void (*init)(struct gdma_dma_dev *dma_dev); + int (*start_transfer)(struct gdma_dmaengine_chan *chan); +}; + +static struct gdma_dma_dev *gdma_dma_chan_get_dev( + struct gdma_dmaengine_chan *chan) +{ + return container_of(chan->vchan.chan.device, struct gdma_dma_dev, + ddev); +} + +static struct gdma_dmaengine_chan *to_gdma_dma_chan(struct dma_chan *c) +{ + return container_of(c, struct gdma_dmaengine_chan, vchan.chan); +} + +static struct gdma_dma_desc *to_gdma_dma_desc(struct virt_dma_desc *vdesc) +{ + return container_of(vdesc, struct gdma_dma_desc, vdesc); +} + +static inline uint32_t gdma_dma_read(struct gdma_dma_dev *dma_dev, + unsigned int reg) +{ + return readl(dma_dev->base + reg); +} + +static inline void gdma_dma_write(struct gdma_dma_dev *dma_dev, + unsigned reg, uint32_t val) +{ + writel(val, dma_dev->base + reg); +} + +static struct gdma_dma_desc *gdma_dma_alloc_desc(unsigned int num_sgs) +{ + return kzalloc(sizeof(struct gdma_dma_desc) + + sizeof(struct gdma_dma_sg) * num_sgs, GFP_ATOMIC); +} + +static enum gdma_dma_transfer_size gdma_dma_maxburst(u32 maxburst) +{ + if (maxburst < 2) + return GDMA_TRANSFER_SIZE_4BYTE; + else if (maxburst < 4) + return GDMA_TRANSFER_SIZE_8BYTE; + else if (maxburst < 8) + return GDMA_TRANSFER_SIZE_16BYTE; + else if (maxburst < 16) + return GDMA_TRANSFER_SIZE_32BYTE; + else + return GDMA_TRANSFER_SIZE_64BYTE; +} + +static int gdma_dma_config(struct dma_chan *c, + struct dma_slave_config *config) +{ + struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); + struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); + + if (config->device_fc) { + dev_err(dma_dev->ddev.dev, "not support flow controller\n"); + return -EINVAL; + } + + switch (config->direction) { + case DMA_MEM_TO_DEV: + if (config->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) { + dev_err(dma_dev->ddev.dev, "only support 4 byte buswidth\n"); + return -EINVAL; + } + chan->slave_id = config->slave_id; + chan->fifo_addr = config->dst_addr; + chan->burst_size = gdma_dma_maxburst(config->dst_maxburst); + break; + case DMA_DEV_TO_MEM: + if (config->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) { + dev_err(dma_dev->ddev.dev, "only support 4 byte buswidth\n"); + return -EINVAL; + } + chan->slave_id = config->slave_id; + chan->fifo_addr = config->src_addr; + chan->burst_size = gdma_dma_maxburst(config->src_maxburst); + break; + default: + dev_err(dma_dev->ddev.dev, "direction type %d error\n", + config->direction); + return -EINVAL; + } + + return 0; +} + +static int gdma_dma_terminate_all(struct dma_chan *c) +{ + struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); + struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); + unsigned long flags, timeout; + LIST_HEAD(head); + int i = 0; + + spin_lock_irqsave(&chan->vchan.lock, flags); + chan->desc = NULL; + clear_bit(chan->id, &dma_dev->chan_issued); + vchan_get_all_descriptors(&chan->vchan, &head); + spin_unlock_irqrestore(&chan->vchan.lock, flags); + + vchan_dma_desc_free_list(&chan->vchan, &head); + + /* wait dma transfer complete */ + timeout = jiffies + msecs_to_jiffies(5000); + while (gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)) & + GDMA_REG_CTRL0_ENABLE) { + if (time_after_eq(jiffies, timeout)) { + dev_err(dma_dev->ddev.dev, "chan %d wait timeout\n", + chan->id); + /* restore to init value */ + gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), 0); + break; + } + cpu_relax(); + i++; + } + + if (i) + dev_dbg(dma_dev->ddev.dev, "terminate chan %d loops %d\n", + chan->id, i); + + return 0; +} + +static void rt305x_dump_reg(struct gdma_dma_dev *dma_dev, int id) +{ + dev_dbg(dma_dev->ddev.dev, "chan %d, src %08x, dst %08x, ctr0 %08x, " \ + "ctr1 %08x, intr %08x, signal %08x\n", id, + gdma_dma_read(dma_dev, GDMA_REG_SRC_ADDR(id)), + gdma_dma_read(dma_dev, GDMA_REG_DST_ADDR(id)), + gdma_dma_read(dma_dev, GDMA_REG_CTRL0(id)), + gdma_dma_read(dma_dev, GDMA_REG_CTRL1(id)), + gdma_dma_read(dma_dev, GDMA_RT305X_STATUS_INT), + gdma_dma_read(dma_dev, GDMA_RT305X_STATUS_SIGNAL)); +} + +static int rt305x_gdma_start_transfer(struct gdma_dmaengine_chan *chan) +{ + struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); + dma_addr_t src_addr, dst_addr; + struct gdma_dma_sg *sg; + uint32_t ctrl0, ctrl1; + + /* verify chan is already stopped */ + ctrl0 = gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)); + if (unlikely(ctrl0 & GDMA_REG_CTRL0_ENABLE)) { + dev_err(dma_dev->ddev.dev, "chan %d is start(%08x).\n", + chan->id, ctrl0); + rt305x_dump_reg(dma_dev, chan->id); + return -EINVAL; + } + + sg = &chan->desc->sg[chan->next_sg]; + if (chan->desc->direction == DMA_MEM_TO_DEV) { + src_addr = sg->src_addr; + dst_addr = chan->fifo_addr; + ctrl0 = GDMA_REG_CTRL0_DST_ADDR_FIXED | \ + (8 << GDMA_RT305X_CTRL0_SRC_REQ_SHIFT) | \ + (chan->slave_id << GDMA_RT305X_CTRL0_DST_REQ_SHIFT); + } else if (chan->desc->direction == DMA_DEV_TO_MEM) { + src_addr = chan->fifo_addr; + dst_addr = sg->dst_addr; + ctrl0 = GDMA_REG_CTRL0_SRC_ADDR_FIXED | \ + (chan->slave_id << GDMA_RT305X_CTRL0_SRC_REQ_SHIFT) | \ + (8 << GDMA_RT305X_CTRL0_DST_REQ_SHIFT); + } else if (chan->desc->direction == DMA_MEM_TO_MEM) { + /* + * TODO: memcpy function have bugs. sometime it will copy + * more 8 bytes data when using dmatest verify. + */ + src_addr = sg->src_addr; + dst_addr = sg->dst_addr; + ctrl0 = GDMA_REG_CTRL0_SW_MODE | \ + (8 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ + (8 << GDMA_REG_CTRL1_DST_REQ_SHIFT); + } else { + dev_err(dma_dev->ddev.dev, "direction type %d error\n", + chan->desc->direction); + return -EINVAL; + } + + ctrl0 |= (sg->len << GDMA_REG_CTRL0_TX_SHIFT) | \ + (chan->burst_size << GDMA_REG_CTRL0_BURST_SHIFT) | \ + GDMA_REG_CTRL0_DONE_INT | GDMA_REG_CTRL0_ENABLE; + ctrl1 = chan->id << GDMA_REG_CTRL1_NEXT_SHIFT; + + chan->next_sg++; + gdma_dma_write(dma_dev, GDMA_REG_SRC_ADDR(chan->id), src_addr); + gdma_dma_write(dma_dev, GDMA_REG_DST_ADDR(chan->id), dst_addr); + gdma_dma_write(dma_dev, GDMA_REG_CTRL1(chan->id), ctrl1); + + /* make sure next_sg is update */ + wmb(); + gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), ctrl0); + + return 0; +} + +static void rt3883_dump_reg(struct gdma_dma_dev *dma_dev, int id) +{ + dev_dbg(dma_dev->ddev.dev, "chan %d, src %08x, dst %08x, ctr0 %08x, " \ + "ctr1 %08x, unmask %08x, done %08x, " \ + "req %08x, ack %08x, fin %08x\n", id, + gdma_dma_read(dma_dev, GDMA_REG_SRC_ADDR(id)), + gdma_dma_read(dma_dev, GDMA_REG_DST_ADDR(id)), + gdma_dma_read(dma_dev, GDMA_REG_CTRL0(id)), + gdma_dma_read(dma_dev, GDMA_REG_CTRL1(id)), + gdma_dma_read(dma_dev, GDMA_REG_UNMASK_INT), + gdma_dma_read(dma_dev, GDMA_REG_DONE_INT), + gdma_dma_read(dma_dev, GDMA_REG_REQSTS), + gdma_dma_read(dma_dev, GDMA_REG_ACKSTS), + gdma_dma_read(dma_dev, GDMA_REG_FINSTS)); +} + +static int rt3883_gdma_start_transfer(struct gdma_dmaengine_chan *chan) +{ + struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); + dma_addr_t src_addr, dst_addr; + struct gdma_dma_sg *sg; + uint32_t ctrl0, ctrl1; + + /* verify chan is already stopped */ + ctrl0 = gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)); + if (unlikely(ctrl0 & GDMA_REG_CTRL0_ENABLE)) { + dev_err(dma_dev->ddev.dev, "chan %d is start(%08x).\n", + chan->id, ctrl0); + rt3883_dump_reg(dma_dev, chan->id); + return -EINVAL; + } + + sg = &chan->desc->sg[chan->next_sg]; + if (chan->desc->direction == DMA_MEM_TO_DEV) { + src_addr = sg->src_addr; + dst_addr = chan->fifo_addr; + ctrl0 = GDMA_REG_CTRL0_DST_ADDR_FIXED; + ctrl1 = (32 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ + (chan->slave_id << GDMA_REG_CTRL1_DST_REQ_SHIFT); + } else if (chan->desc->direction == DMA_DEV_TO_MEM) { + src_addr = chan->fifo_addr; + dst_addr = sg->dst_addr; + ctrl0 = GDMA_REG_CTRL0_SRC_ADDR_FIXED; + ctrl1 = (chan->slave_id << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ + (32 << GDMA_REG_CTRL1_DST_REQ_SHIFT) | \ + GDMA_REG_CTRL1_COHERENT; + } else if (chan->desc->direction == DMA_MEM_TO_MEM) { + src_addr = sg->src_addr; + dst_addr = sg->dst_addr; + ctrl0 = GDMA_REG_CTRL0_SW_MODE; + ctrl1 = (32 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ + (32 << GDMA_REG_CTRL1_DST_REQ_SHIFT) | \ + GDMA_REG_CTRL1_COHERENT; + } else { + dev_err(dma_dev->ddev.dev, "direction type %d error\n", + chan->desc->direction); + return -EINVAL; + } + + ctrl0 |= (sg->len << GDMA_REG_CTRL0_TX_SHIFT) | \ + (chan->burst_size << GDMA_REG_CTRL0_BURST_SHIFT) | \ + GDMA_REG_CTRL0_DONE_INT | GDMA_REG_CTRL0_ENABLE; + ctrl1 |= chan->id << GDMA_REG_CTRL1_NEXT_SHIFT; + + chan->next_sg++; + gdma_dma_write(dma_dev, GDMA_REG_SRC_ADDR(chan->id), src_addr); + gdma_dma_write(dma_dev, GDMA_REG_DST_ADDR(chan->id), dst_addr); + gdma_dma_write(dma_dev, GDMA_REG_CTRL1(chan->id), ctrl1); + + /* make sure next_sg is update */ + wmb(); + gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), ctrl0); + + return 0; +} + +static inline int gdma_start_transfer(struct gdma_dma_dev *dma_dev, + struct gdma_dmaengine_chan *chan) +{ + return dma_dev->data->start_transfer(chan); +} + +static int gdma_next_desc(struct gdma_dmaengine_chan *chan) +{ + struct virt_dma_desc *vdesc; + + vdesc = vchan_next_desc(&chan->vchan); + if (!vdesc) { + chan->desc = NULL; + return 0; + } + chan->desc = to_gdma_dma_desc(vdesc); + chan->next_sg = 0; + + return 1; +} + +static void gdma_dma_chan_irq(struct gdma_dma_dev *dma_dev, + struct gdma_dmaengine_chan *chan) +{ + struct gdma_dma_desc *desc; + unsigned long flags; + int chan_issued; + + chan_issued = 0; + spin_lock_irqsave(&chan->vchan.lock, flags); + desc = chan->desc; + if (desc) { + if (desc->cyclic) { + vchan_cyclic_callback(&desc->vdesc); + if (chan->next_sg == desc->num_sgs) + chan->next_sg = 0; + chan_issued = 1; + } else { + desc->residue -= desc->sg[chan->next_sg - 1].len; + if (chan->next_sg == desc->num_sgs) { + list_del(&desc->vdesc.node); + vchan_cookie_complete(&desc->vdesc); + chan_issued = gdma_next_desc(chan); + } else { + chan_issued = 1; + } + } + } else { + dev_dbg(dma_dev->ddev.dev, "chan %d no desc to complete\n", + chan->id); + } + if (chan_issued) + set_bit(chan->id, &dma_dev->chan_issued); + spin_unlock_irqrestore(&chan->vchan.lock, flags); +} + +static irqreturn_t gdma_dma_irq(int irq, void *devid) +{ + struct gdma_dma_dev *dma_dev = devid; + u32 done, done_reg; + unsigned int i; + + done_reg = dma_dev->data->done_int_reg; + done = gdma_dma_read(dma_dev, done_reg); + if (unlikely(!done)) + return IRQ_NONE; + + /* clean done bits */ + gdma_dma_write(dma_dev, done_reg, done); + + i = 0; + while (done) { + if (done & 0x1) { + gdma_dma_chan_irq(dma_dev, &dma_dev->chan[i]); + atomic_dec(&dma_dev->cnt); + } + done >>= 1; + i++; + } + + /* start only have work to do */ + if (dma_dev->chan_issued) + tasklet_schedule(&dma_dev->task); + + return IRQ_HANDLED; +} + +static void gdma_dma_issue_pending(struct dma_chan *c) +{ + struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); + struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); + unsigned long flags; + + spin_lock_irqsave(&chan->vchan.lock, flags); + if (vchan_issue_pending(&chan->vchan) && !chan->desc) { + if (gdma_next_desc(chan)) { + set_bit(chan->id, &dma_dev->chan_issued); + tasklet_schedule(&dma_dev->task); + } else { + dev_dbg(dma_dev->ddev.dev, "chan %d no desc to issue\n", + chan->id); + } + } + spin_unlock_irqrestore(&chan->vchan.lock, flags); +} + +static struct dma_async_tx_descriptor *gdma_dma_prep_slave_sg( + struct dma_chan *c, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction direction, + unsigned long flags, void *context) +{ + struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); + struct gdma_dma_desc *desc; + struct scatterlist *sg; + unsigned int i; + + desc = gdma_dma_alloc_desc(sg_len); + if (!desc) { + dev_err(c->device->dev, "alloc sg decs error\n"); + return NULL; + } + desc->residue = 0; + + for_each_sg(sgl, sg, sg_len, i) { + if (direction == DMA_MEM_TO_DEV) { + desc->sg[i].src_addr = sg_dma_address(sg); + } else if (direction == DMA_DEV_TO_MEM) { + desc->sg[i].dst_addr = sg_dma_address(sg); + } else { + dev_err(c->device->dev, "direction type %d error\n", + direction); + goto free_desc; + } + + if (unlikely(sg_dma_len(sg) > GDMA_REG_CTRL0_TX_MASK)) { + dev_err(c->device->dev, "sg len too large %d\n", + sg_dma_len(sg)); + goto free_desc; + } + desc->sg[i].len = sg_dma_len(sg); + desc->residue += sg_dma_len(sg); + } + + desc->num_sgs = sg_len; + desc->direction = direction; + desc->cyclic = false; + + return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); + +free_desc: + kfree(desc); + return NULL; +} + +static struct dma_async_tx_descriptor *gdma_dma_prep_dma_memcpy( + struct dma_chan *c, dma_addr_t dest, dma_addr_t src, + size_t len, unsigned long flags) +{ + struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); + struct gdma_dma_desc *desc; + unsigned int num_periods, i; + size_t xfer_count; + + if (len <= 0) + return NULL; + + chan->burst_size = gdma_dma_maxburst(len >> 2); + + xfer_count = GDMA_REG_CTRL0_TX_MASK; + num_periods = DIV_ROUND_UP(len, xfer_count); + + desc = gdma_dma_alloc_desc(num_periods); + if (!desc) { + dev_err(c->device->dev, "alloc memcpy decs error\n"); + return NULL; + } + desc->residue = len; + + for (i = 0; i < num_periods; i++) { + desc->sg[i].src_addr = src; + desc->sg[i].dst_addr = dest; + if (len > xfer_count) + desc->sg[i].len = xfer_count; + else + desc->sg[i].len = len; + src += desc->sg[i].len; + dest += desc->sg[i].len; + len -= desc->sg[i].len; + } + + desc->num_sgs = num_periods; + desc->direction = DMA_MEM_TO_MEM; + desc->cyclic = false; + + return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); +} + +static struct dma_async_tx_descriptor *gdma_dma_prep_dma_cyclic( + struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len, + size_t period_len, enum dma_transfer_direction direction, + unsigned long flags) +{ + struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); + struct gdma_dma_desc *desc; + unsigned int num_periods, i; + + if (buf_len % period_len) + return NULL; + + if (period_len > GDMA_REG_CTRL0_TX_MASK) { + dev_err(c->device->dev, "cyclic len too large %d\n", + period_len); + return NULL; + } + + num_periods = buf_len / period_len; + desc = gdma_dma_alloc_desc(num_periods); + if (!desc) { + dev_err(c->device->dev, "alloc cyclic decs error\n"); + return NULL; + } + desc->residue = buf_len; + + for (i = 0; i < num_periods; i++) { + if (direction == DMA_MEM_TO_DEV) { + desc->sg[i].src_addr = buf_addr; + } else if (direction == DMA_DEV_TO_MEM) { + desc->sg[i].dst_addr = buf_addr; + } else { + dev_err(c->device->dev, "direction type %d error\n", + direction); + goto free_desc; + } + desc->sg[i].len = period_len; + buf_addr += period_len; + } + + desc->num_sgs = num_periods; + desc->direction = direction; + desc->cyclic = true; + + return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); + +free_desc: + kfree(desc); + return NULL; +} + +static enum dma_status gdma_dma_tx_status(struct dma_chan *c, + dma_cookie_t cookie, + struct dma_tx_state *state) +{ + struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); + struct virt_dma_desc *vdesc; + enum dma_status status; + unsigned long flags; + struct gdma_dma_desc *desc; + + status = dma_cookie_status(c, cookie, state); + if (status == DMA_COMPLETE || !state) + return status; + + spin_lock_irqsave(&chan->vchan.lock, flags); + desc = chan->desc; + if (desc && (cookie == desc->vdesc.tx.cookie)) { + /* + * We never update edesc->residue in the cyclic case, so we + * can tell the remaining room to the end of the circular + * buffer. + */ + if (desc->cyclic) + state->residue = desc->residue - + ((chan->next_sg - 1) * desc->sg[0].len); + else + state->residue = desc->residue; + } else { + vdesc = vchan_find_desc(&chan->vchan, cookie); + if (vdesc) + state->residue = to_gdma_dma_desc(vdesc)->residue; + } + spin_unlock_irqrestore(&chan->vchan.lock, flags); + + dev_dbg(c->device->dev, "tx residue %d bytes\n", state->residue); + + return status; +} + +static void gdma_dma_free_chan_resources(struct dma_chan *c) +{ + vchan_free_chan_resources(to_virt_chan(c)); +} + +static void gdma_dma_desc_free(struct virt_dma_desc *vdesc) +{ + kfree(container_of(vdesc, struct gdma_dma_desc, vdesc)); +} + +static void gdma_dma_tasklet(unsigned long arg) +{ + struct gdma_dma_dev *dma_dev = (struct gdma_dma_dev *)arg; + struct gdma_dmaengine_chan *chan; + static unsigned int last_chan; + unsigned int i, chan_mask; + + /* record last chan to round robin all chans */ + i = last_chan; + chan_mask = dma_dev->data->chancnt - 1; + do { + /* + * on mt7621. when verify with dmatest with all + * channel is enable. we need to limit only two + * channel is working at the same time. otherwise the + * data will have problem. + */ + if (atomic_read(&dma_dev->cnt) >= 2) { + last_chan = i; + break; + } + + if (test_and_clear_bit(i, &dma_dev->chan_issued)) { + chan = &dma_dev->chan[i]; + if (chan->desc) { + atomic_inc(&dma_dev->cnt); + gdma_start_transfer(dma_dev, chan); + } else { + dev_dbg(dma_dev->ddev.dev, "chan %d no desc to issue\n", chan->id); + } + if (!dma_dev->chan_issued) + break; + } + + i = (i + 1) & chan_mask; + } while (i != last_chan); +} + +static void rt305x_gdma_init(struct gdma_dma_dev *dma_dev) +{ + uint32_t gct; + + /* all chans round robin */ + gdma_dma_write(dma_dev, GDMA_RT305X_GCT, GDMA_REG_GCT_ARBIT_RR); + + gct = gdma_dma_read(dma_dev, GDMA_RT305X_GCT); + dev_info(dma_dev->ddev.dev, "revision: %d, channels: %d\n", + (gct >> GDMA_REG_GCT_VER_SHIFT) & GDMA_REG_GCT_VER_MASK, + 8 << ((gct >> GDMA_REG_GCT_CHAN_SHIFT) & + GDMA_REG_GCT_CHAN_MASK)); +} + +static void rt3883_gdma_init(struct gdma_dma_dev *dma_dev) +{ + uint32_t gct; + + /* all chans round robin */ + gdma_dma_write(dma_dev, GDMA_REG_GCT, GDMA_REG_GCT_ARBIT_RR); + + gct = gdma_dma_read(dma_dev, GDMA_REG_GCT); + dev_info(dma_dev->ddev.dev, "revision: %d, channels: %d\n", + (gct >> GDMA_REG_GCT_VER_SHIFT) & GDMA_REG_GCT_VER_MASK, + 8 << ((gct >> GDMA_REG_GCT_CHAN_SHIFT) & + GDMA_REG_GCT_CHAN_MASK)); +} + +static struct gdma_data rt305x_gdma_data = { + .chancnt = 8, + .done_int_reg = GDMA_RT305X_STATUS_INT, + .init = rt305x_gdma_init, + .start_transfer = rt305x_gdma_start_transfer, +}; + +static struct gdma_data rt3883_gdma_data = { + .chancnt = 16, + .done_int_reg = GDMA_REG_DONE_INT, + .init = rt3883_gdma_init, + .start_transfer = rt3883_gdma_start_transfer, +}; + +static const struct of_device_id gdma_of_match_table[] = { + { .compatible = "ralink,rt305x-gdma", .data = &rt305x_gdma_data }, + { .compatible = "ralink,rt3883-gdma", .data = &rt3883_gdma_data }, + { }, +}; + +static int gdma_dma_probe(struct platform_device *pdev) +{ + const struct of_device_id *match; + struct gdma_dmaengine_chan *chan; + struct gdma_dma_dev *dma_dev; + struct dma_device *dd; + unsigned int i; + struct resource *res; + int ret; + int irq; + void __iomem *base; + struct gdma_data *data; + + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + match = of_match_device(gdma_of_match_table, &pdev->dev); + if (!match) + return -EINVAL; + data = (struct gdma_data *) match->data; + + dma_dev = devm_kzalloc(&pdev->dev, + struct_size(dma_dev, chan, data->chancnt), + GFP_KERNEL); + if (!dma_dev) { + dev_err(&pdev->dev, "alloc dma device failed\n"); + return -EINVAL; + } + dma_dev->data = data; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + dma_dev->base = base; + tasklet_init(&dma_dev->task, gdma_dma_tasklet, (unsigned long)dma_dev); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get irq\n"); + return -EINVAL; + } + ret = devm_request_irq(&pdev->dev, irq, gdma_dma_irq, + 0, dev_name(&pdev->dev), dma_dev); + if (ret) { + dev_err(&pdev->dev, "failed to request irq\n"); + return ret; + } + + device_reset(&pdev->dev); + + dd = &dma_dev->ddev; + dma_cap_set(DMA_MEMCPY, dd->cap_mask); + dma_cap_set(DMA_SLAVE, dd->cap_mask); + dma_cap_set(DMA_CYCLIC, dd->cap_mask); + dd->device_free_chan_resources = gdma_dma_free_chan_resources; + dd->device_prep_dma_memcpy = gdma_dma_prep_dma_memcpy; + dd->device_prep_slave_sg = gdma_dma_prep_slave_sg; + dd->device_prep_dma_cyclic = gdma_dma_prep_dma_cyclic; + dd->device_config = gdma_dma_config; + dd->device_terminate_all = gdma_dma_terminate_all; + dd->device_tx_status = gdma_dma_tx_status; + dd->device_issue_pending = gdma_dma_issue_pending; + + dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + dd->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); + dd->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; + + dd->dev = &pdev->dev; + dd->dev->dma_parms = &dma_dev->dma_parms; + dma_set_max_seg_size(dd->dev, GDMA_REG_CTRL0_TX_MASK); + INIT_LIST_HEAD(&dd->channels); + + for (i = 0; i < data->chancnt; i++) { + chan = &dma_dev->chan[i]; + chan->id = i; + chan->vchan.desc_free = gdma_dma_desc_free; + vchan_init(&chan->vchan, dd); + } + + /* init hardware */ + data->init(dma_dev); + + ret = dma_async_device_register(dd); + if (ret) { + dev_err(&pdev->dev, "failed to register dma device\n"); + return ret; + } + + ret = of_dma_controller_register(pdev->dev.of_node, + of_dma_xlate_by_chan_id, dma_dev); + if (ret) { + dev_err(&pdev->dev, "failed to register of dma controller\n"); + goto err_unregister; + } + + platform_set_drvdata(pdev, dma_dev); + + return 0; + +err_unregister: + dma_async_device_unregister(dd); + return ret; +} + +static int gdma_dma_remove(struct platform_device *pdev) +{ + struct gdma_dma_dev *dma_dev = platform_get_drvdata(pdev); + + tasklet_kill(&dma_dev->task); + of_dma_controller_free(pdev->dev.of_node); + dma_async_device_unregister(&dma_dev->ddev); + + return 0; +} + +static struct platform_driver gdma_dma_driver = { + .probe = gdma_dma_probe, + .remove = gdma_dma_remove, + .driver = { + .name = "gdma-rt2880", + .of_match_table = gdma_of_match_table, + }, +}; +module_platform_driver(gdma_dma_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Ralink/MTK DMA driver"); +MODULE_LICENSE("GPL v2"); -- cgit From 82f1cebe64ea097a5851386ddee02b4ef45a2ad9 Mon Sep 17 00:00:00 2001 From: Florian Büstgens Date: Tue, 15 Jan 2019 17:16:19 +0100 Subject: staging: rtl8188eu: Refactoring struct ndis_802_11_ssid from CamelCase to correct code style. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rtl8188eu uses CamelCase for many struct members. Refactors the ndis_802_11_ssid members Ssid and SsidLength to keep correct code style. Issue found by checkpatch. Signed-off-by: Florian Büstgens Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_ap.c | 8 ++--- drivers/staging/rtl8188eu/core/rtw_cmd.c | 12 +++---- drivers/staging/rtl8188eu/core/rtw_ieee80211.c | 6 ++-- drivers/staging/rtl8188eu/core/rtw_ioctl_set.c | 12 +++---- drivers/staging/rtl8188eu/core/rtw_mlme.c | 44 ++++++++++++------------- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 38 ++++++++++----------- drivers/staging/rtl8188eu/core/rtw_wlan_util.c | 18 +++++----- drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c | 2 +- drivers/staging/rtl8188eu/include/wlan_bssdef.h | 6 ++-- drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 34 +++++++++---------- drivers/staging/rtl8188eu/os_dep/os_intfs.c | 4 +-- drivers/staging/rtl8188eu/os_dep/rtw_android.c | 2 +- drivers/staging/rtl8188eu/os_dep/usb_intf.c | 6 ++-- 13 files changed, 96 insertions(+), 96 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index 1f232ba6651c..94c9d9f8ee5c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -82,7 +82,7 @@ static void update_BCNTIM(struct adapter *padapter) /* calculate head_len */ offset = _FIXED_IE_LENGTH_; - offset += pnetwork_mlmeext->Ssid.SsidLength + 2; + offset += pnetwork_mlmeext->ssid.ssid_length + 2; /* get supported rates len */ p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, @@ -785,9 +785,9 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) /* SSID */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { - memset(&pbss_network->Ssid, 0, sizeof(struct ndis_802_11_ssid)); - memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len); - pbss_network->Ssid.SsidLength = ie_len; + memset(&pbss_network->ssid, 0, sizeof(struct ndis_802_11_ssid)); + memcpy(pbss_network->ssid.ssid, (p + 2), ie_len); + pbss_network->ssid.ssid_length = ie_len; } /* channel */ diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index 407f65cf7150..83a2e58aef53 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -263,7 +263,7 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int i; for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) { - if (ssid[i].SsidLength) { + if (ssid[i].ssid_length) { memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid)); psurveyPara->ssid_num++; } @@ -316,10 +316,10 @@ u8 rtw_createbss_cmd(struct adapter *padapter) led_control_8188eu(padapter, LED_CTL_START_TO_LINK); - if (pmlmepriv->assoc_ssid.SsidLength == 0) - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.Ssid)); + if (pmlmepriv->assoc_ssid.ssid_length == 0) + RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.ssid)); else - RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid)); + RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.ssid)); pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC); if (!pcmd) { @@ -358,10 +358,10 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) led_control_8188eu(padapter, LED_CTL_START_TO_LINK); - if (pmlmepriv->assoc_ssid.SsidLength == 0) + if (pmlmepriv->assoc_ssid.ssid_length == 0) RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n")); else - RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.Ssid)); + RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.ssid)); pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC); if (!pcmd) { diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 5c4ff81987bd..6ef67c25fdb7 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -234,7 +234,7 @@ int rtw_generate_ie(struct registry_priv *pregistrypriv) ie += 2; /* SSID */ - ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz); + ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->ssid.ssid_length, pdev_network->ssid.ssid, &sz); /* supported rates */ if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) { @@ -975,9 +975,9 @@ void rtw_get_bcn_info(struct wlan_network *pnetwork) pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS; } rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, NULL, &rsn_len, NULL, &wpa_len); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.Ssid.Ssid)); + RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.ssid.ssid)); RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_len =%d rsn_len =%d\n", __func__, wpa_len, rsn_len)); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.Ssid.Ssid)); + RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.ssid.ssid)); RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_len =%d rsn_len =%d\n", __func__, wpa_len, rsn_len)); if (rsn_len > 0) { diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c index 0b3eb0b40975..7d56767cdff6 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c +++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c @@ -77,7 +77,7 @@ u8 rtw_do_join(struct adapter *padapter) pibss = padapter->registrypriv.dev_network.MacAddress; - memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid)); + memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid)); rtw_update_registrypriv_dev_network(padapter); @@ -208,7 +208,7 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid) struct wlan_network *pnetwork = &pmlmepriv->cur_network; DBG_88E_LEVEL(_drv_info_, "set ssid [%s] fw_state=0x%08x\n", - ssid->Ssid, get_fwstate(pmlmepriv)); + ssid->ssid, get_fwstate(pmlmepriv)); if (!padapter->hw_init_completed) { RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, @@ -229,8 +229,8 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid) RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n")); - if (pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength && - !memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength)) { + if (pmlmepriv->assoc_ssid.ssid_length == ssid->ssid_length && + !memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid, ssid->ssid_length)) { if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("Set SSID is the same ssid, fw_state = 0x%08x\n", @@ -257,8 +257,8 @@ u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid) } } else { RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("Set SSID not the same ssid\n")); - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_ssid =[%s] len = 0x%x\n", ssid->Ssid, (unsigned int)ssid->SsidLength)); - RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("assoc_ssid =[%s] len = 0x%x\n", pmlmepriv->assoc_ssid.Ssid, (unsigned int)pmlmepriv->assoc_ssid.SsidLength)); + RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_ssid =[%s] len = 0x%x\n", ssid->ssid, (unsigned int)ssid->ssid_length)); + RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("assoc_ssid =[%s] len = 0x%x\n", pmlmepriv->assoc_ssid.ssid, (unsigned int)pmlmepriv->assoc_ssid.ssid_length)); rtw_disassoc_cmd(padapter, 0, true); diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 714f7a70ed64..ca0cf8a86671 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -300,8 +300,8 @@ int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork) static int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b) { - return (a->Ssid.SsidLength == b->Ssid.SsidLength) && - !memcmp(a->Ssid.Ssid, b->Ssid.Ssid, a->Ssid.SsidLength); + return (a->ssid.ssid_length == b->ssid.ssid_length) && + !memcmp(a->ssid.ssid, b->ssid.ssid, a->ssid.ssid_length); } int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst) @@ -315,9 +315,9 @@ int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst) s_cap = le16_to_cpu(le_scap); d_cap = le16_to_cpu(le_dcap); - return ((src->Ssid.SsidLength == dst->Ssid.SsidLength) && + return ((src->ssid.ssid_length == dst->ssid.ssid_length) && (!memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN)) && - (!memcmp(src->Ssid.Ssid, dst->Ssid.Ssid, src->Ssid.SsidLength)) && + (!memcmp(src->ssid.ssid, dst->ssid.ssid, src->ssid.ssid_length)) && ((s_cap & WLAN_CAPABILITY_IBSS) == (d_cap & WLAN_CAPABILITY_IBSS)) && ((s_cap & WLAN_CAPABILITY_ESS) == @@ -558,7 +558,7 @@ void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf) pnetwork = (struct wlan_bssid_ex *)pbuf; RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("%s, ssid=%s\n", __func__, pnetwork->Ssid.Ssid)); + ("%s, ssid=%s\n", __func__, pnetwork->ssid.ssid)); len = get_wlan_bssid_ex_sz(pnetwork); if (len > (sizeof(struct wlan_bssid_ex))) { @@ -587,8 +587,8 @@ void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf) /* lock pmlmepriv->lock when you accessing network_q */ if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) { - if (pnetwork->Ssid.Ssid[0] == 0) - pnetwork->Ssid.SsidLength = 0; + if (pnetwork->ssid.ssid[0] == 0) + pnetwork->ssid.ssid_length = 0; rtw_add_network(adapter, pnetwork); } @@ -636,7 +636,7 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf) RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("switching to adhoc master\n")); - memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid)); + memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid)); rtw_update_registrypriv_dev_network(adapter); rtw_generate_random_ibss(pibss); @@ -741,7 +741,7 @@ void rtw_free_assoc_resources_locked(struct adapter *adapter) RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_free_assoc_resources\n")); RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("tgt_network->network.MacAddress=%pM ssid=%s\n", - tgt_network->network.MacAddress, tgt_network->network.Ssid.Ssid)); + tgt_network->network.MacAddress, tgt_network->network.ssid.ssid)); if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) { struct sta_info *psta; @@ -975,10 +975,10 @@ void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf) rtw_get_encrypt_decrypt_from_registrypriv(adapter); - if (pmlmepriv->assoc_ssid.SsidLength == 0) + if (pmlmepriv->assoc_ssid.ssid_length == 0) RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ joinbss event call back for Any SSid\n")); else - RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ rtw_joinbss_event_callback for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid)); + RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ rtw_joinbss_event_callback for SSid:%s\n", pmlmepriv->assoc_ssid.ssid)); the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN); @@ -1279,7 +1279,7 @@ void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf) memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network)); - memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid)); + memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid)); rtw_update_registrypriv_dev_network(adapter); @@ -1422,9 +1422,9 @@ static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv } /* check ssid, if needed */ - if (pmlmepriv->assoc_ssid.SsidLength) { - if (competitor->network.Ssid.SsidLength != pmlmepriv->assoc_ssid.SsidLength || - memcmp(competitor->network.Ssid.Ssid, pmlmepriv->assoc_ssid.Ssid, pmlmepriv->assoc_ssid.SsidLength)) + if (pmlmepriv->assoc_ssid.ssid_length) { + if (competitor->network.ssid.ssid_length != pmlmepriv->assoc_ssid.ssid_length || + memcmp(competitor->network.ssid.ssid, pmlmepriv->assoc_ssid.ssid, pmlmepriv->assoc_ssid.ssid_length)) goto exit; } @@ -1445,8 +1445,8 @@ static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv if (updated) { DBG_88E("[by_bssid:%u][assoc_ssid:%s]new candidate: %s(%pM rssi:%d\n", pmlmepriv->assoc_by_bssid, - pmlmepriv->assoc_ssid.Ssid, - (*candidate)->network.Ssid.Ssid, + pmlmepriv->assoc_ssid.ssid, + (*candidate)->network.ssid.ssid, (*candidate)->network.MacAddress, (int)(*candidate)->network.Rssi); DBG_88E("[to_roaming:%u]\n", pmlmepriv->to_roaming); @@ -1493,7 +1493,7 @@ int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv) goto exit; } else { DBG_88E("%s: candidate: %s(%pM ch:%u)\n", __func__, - candidate->network.Ssid.Ssid, candidate->network.MacAddress, + candidate->network.ssid.ssid, candidate->network.MacAddress, candidate->network.Configuration.DSConfig); } @@ -1772,7 +1772,7 @@ void rtw_init_registrypriv_dev_network(struct adapter *adapter) memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN); - memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid)); + memcpy(&pdev_network->ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid)); pdev_network->Configuration.Length = sizeof(struct ndis_802_11_config); pdev_network->Configuration.BeaconPeriod = 100; @@ -2049,9 +2049,9 @@ void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network) if (pmlmepriv->to_roaming > 0) { DBG_88E("roaming from %s(%pM length:%d\n", - pnetwork->network.Ssid.Ssid, pnetwork->network.MacAddress, - pnetwork->network.Ssid.SsidLength); - memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid, sizeof(struct ndis_802_11_ssid)); + pnetwork->network.ssid.ssid, pnetwork->network.MacAddress, + pnetwork->network.ssid.ssid_length); + memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.ssid, sizeof(struct ndis_802_11_ssid)); pmlmepriv->assoc_by_bssid = false; diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 7a36661ebbed..8f28aefbe6f9 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -402,7 +402,7 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms) pattrib->pktlen += 2; /* SSID */ - pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); + pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen); /* supported rates... */ rate_len = rtw_get_rateset_len(cur_network->SupportedRates); @@ -562,7 +562,7 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da) /* below for ad-hoc mode */ /* SSID */ - pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); + pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen); /* supported rates... */ rate_len = rtw_get_rateset_len(cur_network->SupportedRates); @@ -652,7 +652,7 @@ static int issue_probereq(struct adapter *padapter, pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); if (pssid) - pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &pattrib->pktlen); + pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->ssid_length, pssid->ssid, &pattrib->pktlen); else pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &pattrib->pktlen); @@ -1059,7 +1059,7 @@ static void issue_assocreq(struct adapter *padapter) pattrib->pktlen += 2; /* SSID */ - pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &pattrib->pktlen); + pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.ssid.ssid_length, pmlmeinfo->network.ssid.ssid, &pattrib->pktlen); /* supported rate & extended supported rate */ @@ -1929,7 +1929,7 @@ static void site_survey(struct adapter *padapter) int i; for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { - if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) { + if (pmlmeext->sitesurvey_res.ssid[i].ssid_length) { /* todo: to issue two probe req??? */ issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), @@ -2071,10 +2071,10 @@ static u8 collect_bss_info(struct adapter *padapter, DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len); return _FAIL; } - memcpy(bssid->Ssid.Ssid, (p + 2), len); - bssid->Ssid.SsidLength = len; + memcpy(bssid->ssid.ssid, (p + 2), len); + bssid->ssid.ssid_length = len; } else { - bssid->Ssid.SsidLength = 0; + bssid->ssid.ssid_length = 0; } memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); @@ -2526,7 +2526,7 @@ static unsigned int OnProbeReq(struct adapter *padapter, /* check (wildcard) SSID */ if (p) { - if ((ielen != 0 && memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) || + if ((ielen != 0 && memcmp((void *)(p+2), (void *)cur->ssid.ssid, cur->ssid.ssid_length)) || (ielen == 0 && pmlmeinfo->hidden_ssid_mode)) return _SUCCESS; @@ -2975,10 +2975,10 @@ static unsigned int OnAssocReq(struct adapter *padapter, goto OnAssocReqFail; } else { /* check if ssid match */ - if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength)) + if (memcmp((void *)(p+2), cur->ssid.ssid, cur->ssid.ssid_length)) status = _STATS_FAILURE_; - if (ie_len != cur->Ssid.SsidLength) + if (ie_len != cur->ssid.ssid_length) status = _STATS_FAILURE_; } @@ -4658,7 +4658,7 @@ void linked_status_chk(struct adapter *padapter) } if (rx_chk != _SUCCESS) - issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1); + issue_probereq_ex(padapter, &pmlmeinfo->network.ssid, psta->hwaddr, 3, 1); if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) { tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1); @@ -4674,15 +4674,15 @@ void linked_status_chk(struct adapter *padapter) if (rx_chk != _SUCCESS) { if (pmlmeext->retry == 0) { issue_probereq(padapter, - &pmlmeinfo->network.Ssid, + &pmlmeinfo->network.ssid, pmlmeinfo->network.MacAddress, false); issue_probereq(padapter, - &pmlmeinfo->network.Ssid, + &pmlmeinfo->network.ssid, pmlmeinfo->network.MacAddress, false); issue_probereq(padapter, - &pmlmeinfo->network.Ssid, + &pmlmeinfo->network.ssid, pmlmeinfo->network.MacAddress, false); } @@ -5136,11 +5136,11 @@ u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf) pmlmeext->sitesurvey_res.channel_idx = 0; for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { - if (pparm->ssid[i].SsidLength) { - memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE); - pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength; + if (pparm->ssid[i].ssid_length) { + memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid, pparm->ssid[i].ssid, IW_ESSID_MAX_SIZE); + pmlmeext->sitesurvey_res.ssid[i].ssid_length = pparm->ssid[i].ssid_length; } else { - pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0; + pmlmeext->sitesurvey_res.ssid[i].ssid_length = 0; } } diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 5f9c9de1f1da..4480deef95a1 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -935,17 +935,17 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) if (ssid_len > NDIS_802_11_LENGTH_SSID) ssid_len = 0; } - memcpy(bssid->Ssid.Ssid, (p + 2), ssid_len); - bssid->Ssid.SsidLength = ssid_len; + memcpy(bssid->ssid.ssid, (p + 2), ssid_len); + bssid->ssid.ssid_length = ssid_len; - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d " - "cur_network->network.Ssid.Ssid:%s len:%d\n", __func__, bssid->Ssid.Ssid, - bssid->Ssid.SsidLength, cur_network->network.Ssid.Ssid, - cur_network->network.Ssid.SsidLength)); + RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s bssid.ssid.ssid:%s bssid.ssid.ssid_length:%d " + "cur_network->network.ssid.ssid:%s len:%d\n", __func__, bssid->ssid.ssid, + bssid->ssid.ssid_length, cur_network->network.ssid.ssid, + cur_network->network.ssid.ssid_length)); - if (memcmp(bssid->Ssid.Ssid, cur_network->network.Ssid.Ssid, 32) || - bssid->Ssid.SsidLength != cur_network->network.Ssid.SsidLength) { - if (bssid->Ssid.Ssid[0] != '\0' && bssid->Ssid.SsidLength != 0) { /* not hidden ssid */ + if (memcmp(bssid->ssid.ssid, cur_network->network.ssid.ssid, 32) || + bssid->ssid.ssid_length != cur_network->network.ssid.ssid_length) { + if (bssid->ssid.ssid[0] != '\0' && bssid->ssid.ssid_length != 0) { /* not hidden ssid */ DBG_88E("%s(), SSID is not match return FAIL\n", __func__); goto _mismatch; } diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index 7022221136f6..491d948e9f2a 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -257,7 +257,7 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength) /* below for ad-hoc mode */ /* SSID */ - pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen); + pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pktlen); /* supported rates... */ rate_len = rtw_get_rateset_len(cur_network->SupportedRates); diff --git a/drivers/staging/rtl8188eu/include/wlan_bssdef.h b/drivers/staging/rtl8188eu/include/wlan_bssdef.h index 5e13a6ddf083..8462c9c2fd39 100644 --- a/drivers/staging/rtl8188eu/include/wlan_bssdef.h +++ b/drivers/staging/rtl8188eu/include/wlan_bssdef.h @@ -17,8 +17,8 @@ #define NDIS_802_11_RSSI long /* in dBm */ struct ndis_802_11_ssid { - u32 SsidLength; - u8 Ssid[32]; + u32 ssid_length; + u8 ssid[32]; }; enum NDIS_802_11_NETWORK_TYPE { @@ -180,7 +180,7 @@ struct wlan_bssid_ex { u32 Length; unsigned char MacAddress[ETH_ALEN]; u8 Reserved[2];/* 0]: IS beacon frame */ - struct ndis_802_11_ssid Ssid; + struct ndis_802_11_ssid ssid; u32 Privacy; NDIS_802_11_RSSI Rssi;/* in dBM,raw data ,get from PHY) */ enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index efaa1c779f4b..eaa4adb32a0d 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -116,8 +116,8 @@ static char *translate_scan(struct adapter *padapter, /* Add the ESSID */ iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; - iwe.u.data.length = min_t(u16, pnetwork->network.Ssid.SsidLength, 32); - start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid); + iwe.u.data.length = min_t(u16, pnetwork->network.ssid.ssid_length, 32); + start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.ssid.ssid); /* parsing HT_CAP_IE */ p = rtw_get_ie(&pnetwork->network.ies[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.ie_length-12); @@ -195,7 +195,7 @@ static char *translate_scan(struct adapter *padapter, else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; - start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid); + start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.ssid.ssid); /*Add basic and extended rates */ max_rate = 0; @@ -235,7 +235,7 @@ static char *translate_scan(struct adapter *padapter, u8 *p; rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, rsn_ie, &rsn_len, wpa_ie, &wpa_len); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.Ssid.Ssid)); + RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.ssid.ssid)); RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len)); if (wpa_len > 0) { @@ -1124,8 +1124,8 @@ static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a, int len = min_t(int, req->essid_len, IW_ESSID_MAX_SIZE); - memcpy(ssid[0].Ssid, req->essid, len); - ssid[0].SsidLength = len; + memcpy(ssid[0].ssid, req->essid, len); + ssid[0].ssid_length = len; DBG_88E("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len); @@ -1158,8 +1158,8 @@ static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a, } sec_len = *(pos++); len -= 1; if (sec_len > 0 && sec_len <= len) { - ssid[ssid_index].SsidLength = sec_len; - memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength); + ssid[ssid_index].ssid_length = sec_len; + memcpy(ssid[ssid_index].ssid, pos, ssid[ssid_index].ssid_length); ssid_index++; } pos += sec_len; @@ -1310,9 +1310,9 @@ static int rtw_wx_set_essid(struct net_device *dev, DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length); memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid)); - ndis_ssid.SsidLength = len; - memcpy(ndis_ssid.Ssid, extra, len); - src_ssid = ndis_ssid.Ssid; + ndis_ssid.ssid_length = len; + memcpy(ndis_ssid.ssid, extra, len); + src_ssid = ndis_ssid.ssid; RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid =[%s]\n", src_ssid)); spin_lock_bh(&queue->lock); @@ -1324,14 +1324,14 @@ static int rtw_wx_set_essid(struct net_device *dev, pmlmepriv->pscanned = pmlmepriv->pscanned->next; - dst_ssid = pnetwork->network.Ssid.Ssid; + dst_ssid = pnetwork->network.ssid.ssid; RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: dst_ssid =%s\n", - pnetwork->network.Ssid.Ssid)); + pnetwork->network.ssid.ssid)); - if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength)) && - (pnetwork->network.Ssid.SsidLength == ndis_ssid.SsidLength)) { + if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.ssid_length)) && + (pnetwork->network.ssid.ssid_length == ndis_ssid.ssid_length)) { RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: find match, set infra mode\n")); @@ -1378,8 +1378,8 @@ static int rtw_wx_get_essid(struct net_device *dev, if ((check_fwstate(pmlmepriv, _FW_LINKED)) || (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) { - len = pcur_bss->Ssid.SsidLength; - memcpy(extra, pcur_bss->Ssid.Ssid, len); + len = pcur_bss->ssid.ssid_length; + memcpy(extra, pcur_bss->ssid.ssid, len); } else { len = 0; *extra = 0; diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 6681383579ee..72fa446cb953 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -141,8 +141,8 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev) GlobalDebugLevel = rtw_debug; - memcpy(registry_par->ssid.Ssid, "ANY", 3); - registry_par->ssid.SsidLength = 3; + memcpy(registry_par->ssid.ssid, "ANY", 3); + registry_par->ssid.ssid_length = 3; registry_par->channel = (u8)rtw_channel; registry_par->wireless_mode = (u8)rtw_wireless_mode; diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_android.c b/drivers/staging/rtl8188eu/os_dep/rtw_android.c index 2ea2af3286bc..7a090615dcbc 100644 --- a/drivers/staging/rtl8188eu/os_dep/rtw_android.c +++ b/drivers/staging/rtl8188eu/os_dep/rtw_android.c @@ -84,7 +84,7 @@ static int rtw_android_get_rssi(struct net_device *net, char *command, if (check_fwstate(pmlmepriv, _FW_LINKED)) { bytes_written += snprintf(&command[bytes_written], total_len, "%s rssi %d", - pcur_network->network.Ssid.Ssid, + pcur_network->network.ssid.ssid, padapter->recvpriv.rssi); } return bytes_written; diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 28cbd6b3d26c..1859ec3281e8 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -227,10 +227,10 @@ static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) check_fwstate(pmlmepriv, _FW_LINKED)) { pr_debug("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n", __func__, __LINE__, - pmlmepriv->cur_network.network.Ssid.Ssid, + pmlmepriv->cur_network.network.ssid.ssid, pmlmepriv->cur_network.network.MacAddress, - pmlmepriv->cur_network.network.Ssid.SsidLength, - pmlmepriv->assoc_ssid.SsidLength); + pmlmepriv->cur_network.network.ssid.ssid_length, + pmlmepriv->assoc_ssid.ssid_length); pmlmepriv->to_roaming = 1; } -- cgit From 56eec1806fac3cc585eb8644e36e8cc30bcbcbb1 Mon Sep 17 00:00:00 2001 From: Jitendra Khasdev Date: Tue, 15 Jan 2019 21:06:56 +0530 Subject: staging: comedi: Removed not necessary braces for single block This patch is used to remove not necessary braces for single if block. Signed-off-by: Jitendra Khasdev Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 5d2fcbfe02af..38980fad8be4 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1605,9 +1605,9 @@ static int do_insn_ioctl(struct comedi_device *dev, unsigned int n_data = MIN_SAMPLES; int ret = 0; - if (copy_from_user(&insn, arg, sizeof(insn))) { + if (copy_from_user(&insn, arg, sizeof(insn))) return -EFAULT; - } + n_data = max(n_data, insn.n); -- cgit From 58d37ddf75a481605c9316392988a2ab87cc24b2 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Tue, 15 Jan 2019 17:36:39 +0100 Subject: staging: rtl8188eu: cleanup declarations in os_intfs.c Replace tabs with spaces and/or remove extra spaces in declarations. Signed-off-by: Michael Straube Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/os_intfs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 72fa446cb953..130d7261f20e 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -137,7 +137,7 @@ static int netdev_close(struct net_device *pnetdev); static void loadparam(struct adapter *padapter, struct net_device *pnetdev) { - struct registry_priv *registry_par = &padapter->registrypriv; + struct registry_priv *registry_par = &padapter->registrypriv; GlobalDebugLevel = rtw_debug; @@ -248,7 +248,7 @@ static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev, select_queue_fallback_t fallback) { - struct adapter *padapter = rtw_netdev_priv(dev); + struct adapter *padapter = rtw_netdev_priv(dev); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; skb->priority = rtw_classify8021d(skb); @@ -263,7 +263,7 @@ u16 rtw_recv_select_queue(struct sk_buff *skb) { struct iphdr *piphdr; unsigned int dscp; - __be16 eth_type; + __be16 eth_type; u32 priority; u8 *pdata = skb->data; @@ -286,7 +286,7 @@ static const struct net_device_ops rtw_netdev_ops = { .ndo_open = netdev_open, .ndo_stop = netdev_close, .ndo_start_xmit = rtw_xmit_entry, - .ndo_select_queue = rtw_select_queue, + .ndo_select_queue = rtw_select_queue, .ndo_set_mac_address = rtw_net_set_mac_address, .ndo_get_stats = rtw_net_get_stats, .ndo_do_ioctl = rtw_ioctl, @@ -361,7 +361,7 @@ void rtw_stop_drv_threads(struct adapter *padapter) static u8 rtw_init_default_value(struct adapter *padapter) { struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct security_priv *psecuritypriv = &padapter->securitypriv; @@ -431,7 +431,7 @@ u8 rtw_reset_drv_sw(struct adapter *padapter) u8 rtw_init_drv_sw(struct adapter *padapter) { - u8 ret8 = _SUCCESS; + u8 ret8 = _SUCCESS; RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_init_drv_sw\n")); -- cgit From 9435bbd4b9d95280230bae09bad9e136941a500a Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Tue, 15 Jan 2019 17:36:40 +0100 Subject: staging: rtl8188eu: add spaces around operators in os_intfs.c Add spaces around '+', '<<' and '*' to follow kernel coding style. Reported by checkpatch. Signed-off-by: Michael Straube Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/os_intfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 130d7261f20e..8dde5a40e253 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -267,11 +267,11 @@ u16 rtw_recv_select_queue(struct sk_buff *skb) u32 priority; u8 *pdata = skb->data; - memcpy(ð_type, pdata+(ETH_ALEN<<1), 2); + memcpy(ð_type, pdata + (ETH_ALEN << 1), 2); switch (eth_type) { case htons(ETH_P_IP): - piphdr = (struct iphdr *)(pdata+ETH_HLEN); + piphdr = (struct iphdr *)(pdata + ETH_HLEN); dscp = piphdr->tos & 0xfc; priority = dscp >> 5; break; @@ -323,7 +323,7 @@ struct net_device *rtw_init_netdev(struct adapter *old_padapter) padapter->pnetdev = pnetdev; DBG_88E("register rtw_netdev_ops to netdev_ops\n"); pnetdev->netdev_ops = &rtw_netdev_ops; - pnetdev->watchdog_timeo = HZ*3; /* 3 second timeout */ + pnetdev->watchdog_timeo = HZ * 3; /* 3 second timeout */ pnetdev->wireless_handlers = (struct iw_handler_def *)&rtw_handlers_def; loadparam(padapter, pnetdev); -- cgit From 6e3da68c7f8c645e0ea07b158ab56965bac4ea2d Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Thu, 17 Jan 2019 20:23:00 +0100 Subject: staging: rtl8188eu: add spaces around operators in mlme_linux.c Add spaces around '+' and '-' to follow kernel coding style. Reported by checkpatch. Signed-off-by: Michael Straube Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/mlme_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c index d5ceb3beabbc..8180769610c3 100644 --- a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c @@ -99,13 +99,13 @@ void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie) memset(buff, 0, IW_CUSTOM_MAX); p = buff; p += sprintf(p, "ASSOCINFO(ReqIEs ="); - len = sec_ie[1]+2; + len = sec_ie[1] + 2; len = min_t(uint, len, IW_CUSTOM_MAX); for (i = 0; i < len; i++) p += sprintf(p, "%02x", sec_ie[i]); p += sprintf(p, ")"); memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = p-buff; + wrqu.data.length = p - buff; wrqu.data.length = min_t(__u16, wrqu.data.length, IW_CUSTOM_MAX); wireless_send_event(adapter->pnetdev, IWEVCUSTOM, &wrqu, buff); kfree(buff); -- cgit From 01f7e722aa9f0ba7df34ac5cdcc1c12e86792567 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Thu, 17 Jan 2019 20:23:01 +0100 Subject: staging: rtl8188eu: cleanup indenting issue in mlme_linux.c Cleanup indenting issue reported by checkpatch. CHECK: Alignment should match open parenthesis Signed-off-by: Michael Straube Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/mlme_linux.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c index 8180769610c3..2bc49d074ce4 100644 --- a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c @@ -52,9 +52,8 @@ void rtw_reset_securitypriv(struct adapter *adapter) memset((unsigned char *)&adapter->securitypriv, 0, sizeof(struct security_priv)); /* Restore the PMK information to securitypriv structure for the following connection. */ - memcpy(&adapter->securitypriv.PMKIDList[0], - &backup_pmkid[0], - sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); + memcpy(&adapter->securitypriv.PMKIDList[0], &backup_pmkid[0], + sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE); adapter->securitypriv.PMKIDIndex = backup_index; adapter->securitypriv.btkip_countermeasure = backup_counter; adapter->securitypriv.btkip_countermeasure_time = backup_time; -- cgit From 61c9314fdd303b99c8cd52bd64998d7296b36a3e Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 16 Jan 2019 16:59:52 +0800 Subject: staging: erofs: sunset erofs_workstation_cleanup_all There is only one user calling erofs_workstation_cleanup_all, and it is no likely that more users will use in that way in the future. Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 5 ----- drivers/staging/erofs/super.c | 3 ++- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index c3de24e7fb67..80cc09ea787d 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -283,11 +283,6 @@ extern int erofs_register_workgroup(struct super_block *sb, extern unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, unsigned long nr_shrink, bool cleanup); -static inline void erofs_workstation_cleanup_all(struct super_block *sb) -{ - erofs_shrink_workstation(EROFS_SB(sb), ~0UL, true); -} - extern void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); #ifdef EROFS_FS_HAS_MANAGED_CACHE diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 45c7f6ddb9f5..69e1840d3842 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -494,7 +494,8 @@ static void erofs_put_super(struct super_block *sb) mutex_lock(&sbi->umount_mutex); #ifdef CONFIG_EROFS_FS_ZIP - erofs_workstation_cleanup_all(sb); + /* clean up the compression space of this sb */ + erofs_shrink_workstation(EROFS_SB(sb), ~0UL, true); #endif erofs_unregister_super(sb); -- cgit From d60eff4396f1f7423945f01acc274043c1370bc7 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 16 Jan 2019 16:59:53 +0800 Subject: staging: erofs: localize erofs_workgroup_get Staticize erofs_workgroup_get since no external user out of utils.c directly calls erofs_workgroup_get. Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 21 --------------------- drivers/staging/erofs/utils.c | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 80cc09ea787d..967ec1a56726 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -252,28 +252,7 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) } #endif -static inline int erofs_workgroup_get(struct erofs_workgroup *grp, int *ocnt) -{ - int o; - -repeat: - o = erofs_wait_on_workgroup_freezed(grp); - - if (unlikely(o <= 0)) - return -1; - - if (unlikely(atomic_cmpxchg(&grp->refcount, o, o + 1) != o)) - goto repeat; - - *ocnt = o; - return 0; -} - -#define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount) -#define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount) - extern int erofs_workgroup_put(struct erofs_workgroup *grp); - extern struct erofs_workgroup *erofs_find_workgroup( struct super_block *sb, pgoff_t index, bool *tag); diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index aed211cd5875..d24945aab133 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -31,6 +31,25 @@ struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp) static atomic_long_t erofs_global_shrink_cnt; #ifdef CONFIG_EROFS_FS_ZIP +#define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount) +#define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount) + +static int erofs_workgroup_get(struct erofs_workgroup *grp, int *ocnt) +{ + int o; + +repeat: + o = erofs_wait_on_workgroup_freezed(grp); + + if (unlikely(o <= 0)) + return -1; + + if (unlikely(atomic_cmpxchg(&grp->refcount, o, o + 1) != o)) + goto repeat; + + *ocnt = o; + return 0; +} struct erofs_workgroup *erofs_find_workgroup( struct super_block *sb, pgoff_t index, bool *tag) -- cgit From 4501ca36bc18ee73a3e88373ff50c22233b82324 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 16 Jan 2019 21:10:10 +0800 Subject: staging: erofs: move shrink accounting inside the function This patch moves the &erofs_global_shrink_cnt accounting from the caller to erofs_workgroup_get(). It's cleaner and it matches erofs_workgroup_put() better. No behavior change. Reviewed-by: Chao Yu Reviewed-by: Dan Carpenter Signed-off-by: Gao Xiang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/utils.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index d24945aab133..5695efaeb43a 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -34,29 +34,29 @@ static atomic_long_t erofs_global_shrink_cnt; #define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount) #define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount) -static int erofs_workgroup_get(struct erofs_workgroup *grp, int *ocnt) +static int erofs_workgroup_get(struct erofs_workgroup *grp) { int o; repeat: o = erofs_wait_on_workgroup_freezed(grp); - if (unlikely(o <= 0)) return -1; if (unlikely(atomic_cmpxchg(&grp->refcount, o, o + 1) != o)) goto repeat; - *ocnt = o; + /* decrease refcount paired by erofs_workgroup_put */ + if (unlikely(o == 1)) + atomic_long_dec(&erofs_global_shrink_cnt); return 0; } -struct erofs_workgroup *erofs_find_workgroup( - struct super_block *sb, pgoff_t index, bool *tag) +struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, + pgoff_t index, bool *tag) { struct erofs_sb_info *sbi = EROFS_SB(sb); struct erofs_workgroup *grp; - int oldcount; repeat: rcu_read_lock(); @@ -65,15 +65,12 @@ repeat: *tag = xa_pointer_tag(grp); grp = xa_untag_pointer(grp); - if (erofs_workgroup_get(grp, &oldcount)) { + if (erofs_workgroup_get(grp)) { /* prefer to relax rcu read side */ rcu_read_unlock(); goto repeat; } - /* decrease refcount added by erofs_workgroup_put */ - if (unlikely(oldcount == 1)) - atomic_long_dec(&erofs_global_shrink_cnt); DBG_BUGON(index != grp->index); } rcu_read_unlock(); -- cgit From d55bc7ba6bee8950d036089a0d6cb8cb71ff2913 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 16 Jan 2019 16:59:55 +0800 Subject: staging: erofs: staticize erofs_shrink_count, erofs_shrink_scan Move erofs_shrinker_info to utils.c and therefore no need to globalize erofs_shrink_count and erofs_shrink_scan. Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 5 +---- drivers/staging/erofs/super.c | 6 ------ drivers/staging/erofs/utils.c | 14 ++++++++++---- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 967ec1a56726..304c79d253ae 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -589,10 +589,7 @@ extern struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); extern void erofs_register_super(struct super_block *sb); extern void erofs_unregister_super(struct super_block *sb); -extern unsigned long erofs_shrink_count(struct shrinker *shrink, - struct shrink_control *sc); -extern unsigned long erofs_shrink_scan(struct shrinker *shrink, - struct shrink_control *sc); +extern struct shrinker erofs_shrinker_info; #ifndef lru_to_page #define lru_to_page(head) (list_entry((head)->prev, struct page, lru)) diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 69e1840d3842..af5140eede18 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -539,12 +539,6 @@ static void erofs_kill_sb(struct super_block *sb) kill_block_super(sb); } -static struct shrinker erofs_shrinker_info = { - .scan_objects = erofs_shrink_scan, - .count_objects = erofs_shrink_count, - .seeks = DEFAULT_SEEKS, -}; - static struct file_system_type erofs_fs_type = { .owner = THIS_MODULE, .name = "erofs", diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 5695efaeb43a..5f61f99f4c10 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -270,14 +270,14 @@ void erofs_unregister_super(struct super_block *sb) spin_unlock(&erofs_sb_list_lock); } -unsigned long erofs_shrink_count(struct shrinker *shrink, - struct shrink_control *sc) +static unsigned long erofs_shrink_count(struct shrinker *shrink, + struct shrink_control *sc) { return atomic_long_read(&erofs_global_shrink_cnt); } -unsigned long erofs_shrink_scan(struct shrinker *shrink, - struct shrink_control *sc) +static unsigned long erofs_shrink_scan(struct shrinker *shrink, + struct shrink_control *sc) { struct erofs_sb_info *sbi; struct list_head *p; @@ -333,3 +333,9 @@ unsigned long erofs_shrink_scan(struct shrinker *shrink, return freed; } +struct shrinker erofs_shrinker_info = { + .scan_objects = erofs_shrink_scan, + .count_objects = erofs_shrink_count, + .seeks = DEFAULT_SEEKS, +}; + -- cgit From 2e1d66379ece5b8c81c748faab1ae5fe3487c592 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 16 Jan 2019 16:59:56 +0800 Subject: staging: erofs: drop the extern prefix for function definitions Fix all `CHECK: extern prototypes should be avoided in .h files' reported by checkpatch.pl. Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 47 +++++++++++++++++---------------------- drivers/staging/erofs/unzip_vle.h | 24 ++++++++++---------- 2 files changed, 33 insertions(+), 38 deletions(-) diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 304c79d253ae..3a27c255950b 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -252,23 +252,20 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) } #endif -extern int erofs_workgroup_put(struct erofs_workgroup *grp); -extern struct erofs_workgroup *erofs_find_workgroup( - struct super_block *sb, pgoff_t index, bool *tag); - -extern int erofs_register_workgroup(struct super_block *sb, - struct erofs_workgroup *grp, bool tag); - -extern unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, - unsigned long nr_shrink, bool cleanup); - -extern void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); +int erofs_workgroup_put(struct erofs_workgroup *grp); +struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, + pgoff_t index, bool *tag); +int erofs_register_workgroup(struct super_block *sb, + struct erofs_workgroup *grp, bool tag); +unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, + unsigned long nr_shrink, bool cleanup); +void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); #ifdef EROFS_FS_HAS_MANAGED_CACHE -extern int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, - struct erofs_workgroup *egrp); -extern int erofs_try_to_free_cached_page(struct address_space *mapping, - struct page *page); +int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, + struct erofs_workgroup *egrp); +int erofs_try_to_free_cached_page(struct address_space *mapping, + struct page *page); #define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) #else @@ -495,8 +492,8 @@ static inline void __submit_bio(struct bio *bio, unsigned op, unsigned op_flags) #define EROFS_IO_MAX_RETRIES_NOFAIL CONFIG_EROFS_FS_IO_MAX_RETRIES #endif -extern struct page *__erofs_get_meta_page(struct super_block *sb, - erofs_blk_t blkaddr, bool prio, bool nofail); +struct page *__erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr, + bool prio, bool nofail); static inline struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr, bool prio) @@ -510,7 +507,7 @@ static inline struct page *erofs_get_meta_page_nofail(struct super_block *sb, return __erofs_get_meta_page(sb, blkaddr, prio, true); } -extern int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int); +int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int); static inline struct page * erofs_get_inline_page(struct inode *inode, @@ -530,9 +527,6 @@ static inline unsigned long erofs_inode_hash(erofs_nid_t nid) #endif } -extern struct inode *erofs_iget(struct super_block *sb, - erofs_nid_t nid, bool dir); - extern const struct inode_operations erofs_generic_iops; extern const struct inode_operations erofs_symlink_iops; extern const struct inode_operations erofs_fast_symlink_iops; @@ -547,6 +541,8 @@ static inline bool is_inode_fast_symlink(struct inode *inode) return inode->i_op == &erofs_fast_symlink_iops; } +struct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid, bool dir); + /* namei.c */ extern const struct inode_operations erofs_dir_iops; @@ -584,13 +580,12 @@ static inline void erofs_vunmap(const void *mem, unsigned int count) } /* utils.c */ -extern struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); - -extern void erofs_register_super(struct super_block *sb); -extern void erofs_unregister_super(struct super_block *sb); - extern struct shrinker erofs_shrinker_info; +struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); +void erofs_register_super(struct super_block *sb); +void erofs_unregister_super(struct super_block *sb); + #ifndef lru_to_page #define lru_to_page(head) (list_entry((head)->prev, struct page, lru)) #endif diff --git a/drivers/staging/erofs/unzip_vle.h b/drivers/staging/erofs/unzip_vle.h index 5a4e1b62c0d1..9dafa8dc712c 100644 --- a/drivers/staging/erofs/unzip_vle.h +++ b/drivers/staging/erofs/unzip_vle.h @@ -212,18 +212,18 @@ static inline void z_erofs_onlinepage_endio(struct page *page) #define Z_EROFS_VLE_VMAP_GLOBAL_PAGES 2048 /* unzip_vle_lz4.c */ -extern int z_erofs_vle_plain_copy(struct page **compressed_pages, - unsigned clusterpages, struct page **pages, - unsigned nr_pages, unsigned short pageofs); - -extern int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages, - unsigned clusterpages, struct page **pages, - unsigned outlen, unsigned short pageofs, - void (*endio)(struct page *)); - -extern int z_erofs_vle_unzip_vmap(struct page **compressed_pages, - unsigned clusterpages, void *vaddr, unsigned llen, - unsigned short pageofs, bool overlapped); +int z_erofs_vle_plain_copy(struct page **compressed_pages, + unsigned int clusterpages, struct page **pages, + unsigned int nr_pages, unsigned short pageofs); +int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages, + unsigned int clusterpages, + struct page **pages, unsigned int outlen, + unsigned short pageofs, + void (*endio)(struct page *)); +int z_erofs_vle_unzip_vmap(struct page **compressed_pages, + unsigned int clusterpages, + void *vaddr, unsigned int llen, + unsigned short pageofs, bool overlapped); #endif -- cgit From 92f6de4340ae7e1fa441bd1aaf38ce1efa2618b1 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 17 Jan 2019 13:21:10 +0000 Subject: staging: wilc1000: make use of get_unaligned_le16/le32 to pack data Make use of get_unaligned_le16/le32 framework api's to pack data. Signed-off-by: Ajay Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 15 +++------------ drivers/staging/wilc1000/wilc_wlan_cfg.c | 27 +++++++++++++-------------- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c05c120fafc7..a71884287fca 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -2154,10 +2154,7 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length) struct host_if_drv *hif_drv; struct wilc_vif *vif; - id = buffer[length - 4]; - id |= (buffer[length - 3] << 8); - id |= (buffer[length - 2] << 16); - id |= (buffer[length - 1] << 24); + id = get_unaligned_le32(&buffer[length - 4]); vif = wilc_get_vif_from_idx(wilc, id); if (!vif) return; @@ -2197,10 +2194,7 @@ void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length) mutex_lock(&hif_deinit_lock); - id = buffer[length - 4]; - id |= (buffer[length - 3] << 8); - id |= (buffer[length - 2] << 16); - id |= (buffer[length - 1] << 24); + id = get_unaligned_le32(&buffer[length - 4]); vif = wilc_get_vif_from_idx(wilc, id); if (!vif) { mutex_unlock(&hif_deinit_lock); @@ -2251,10 +2245,7 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length) struct host_if_drv *hif_drv; struct wilc_vif *vif; - id = buffer[length - 4]; - id |= buffer[length - 3] << 8; - id |= buffer[length - 2] << 16; - id |= buffer[length - 1] << 24; + id = get_unaligned_le32(&buffer[length - 4]); vif = wilc_get_vif_from_idx(wilc, id); if (!vif) return; diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index 8390766358da..67e9f93f7eaa 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -168,7 +168,7 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size) while (size > 0) { i = 0; - wid = info[0] | (info[1] << 8); + wid = get_unaligned_le16(info); switch (GET_WID_TYPE(wid)) { case WID_CHAR: @@ -187,12 +187,13 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size) case WID_SHORT: do { - if (wl->cfg.hw[i].id == WID_NIL) + struct wilc_cfg_hword *hw = &wl->cfg.hw[i]; + + if (hw->id == WID_NIL) break; - if (wl->cfg.hw[i].id == wid) { - wl->cfg.hw[i].val = (info[4] | - (info[5] << 8)); + if (hw->id == wid) { + hw->val = get_unaligned_le16(&info[4]); break; } i++; @@ -202,14 +203,13 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size) case WID_INT: do { - if (wl->cfg.w[i].id == WID_NIL) + struct wilc_cfg_word *w = &wl->cfg.w[i]; + + if (w->id == WID_NIL) break; - if (wl->cfg.w[i].id == wid) { - wl->cfg.w[i].val = (info[4] | - (info[5] << 8) | - (info[6] << 16) | - (info[7] << 24)); + if (w->id == wid) { + w->val = get_unaligned_le32(&info[4]); break; } i++; @@ -244,7 +244,7 @@ static void wilc_wlan_parse_info_frame(struct wilc *wl, u8 *info) { u32 wid, len; - wid = info[0] | (info[1] << 8); + wid = get_unaligned_le16(info); len = info[2]; @@ -371,8 +371,7 @@ int wilc_wlan_cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer, break; if (id == wid) { - u32 size = (wl->cfg.s[i].str[0] | - (wl->cfg.s[i].str[1] << 8)); + u16 size = get_unaligned_le16(wl->cfg.s[i].str); if (buffer_size >= size) { memcpy(buffer, &wl->cfg.s[i].str[2], -- cgit From 4e90d5f3e85c538efd0ae059d5ccfdab3a388b49 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 17 Jan 2019 13:21:13 +0000 Subject: staging: wilc1000: refactor wilc_wlan_set_bssid() Refactor code by making use of eth_zero_addr() to clear the mac address value in wilc_wlan_set_bssid(). Signed-off-by: Ajay Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 6 +++++- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 16 +++++----------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 721689048648..5b554c6d39a1 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -198,7 +198,11 @@ void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode) { struct wilc_vif *vif = netdev_priv(wilc_netdev); - memcpy(vif->bssid, bssid, 6); + if (bssid) + ether_addr_copy(vif->bssid, bssid); + else + eth_zero_addr(vif->bssid); + vif->mode = mode; } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index ac47dda510e0..987e5ff0e44a 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -390,7 +390,6 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, struct wilc_vif *vif = netdev_priv(dev); struct wilc *wl = vif->wilc; struct host_if_drv *wfi_drv = priv->hif_drv; - u8 null_bssid[ETH_ALEN] = {0}; vif->connecting = false; @@ -402,8 +401,7 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, if (mac_status == WILC_MAC_STATUS_DISCONNECTED && conn_info->status == WLAN_STATUS_SUCCESS) { connect_status = WLAN_STATUS_UNSPECIFIED_FAILURE; - wilc_wlan_set_bssid(priv->dev, null_bssid, - WILC_STATION_MODE); + wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE); if (!wfi_drv->p2p_connect) wlan_channel = INVALID_CHANNEL; @@ -445,7 +443,7 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, priv->p2p.recv_random = 0x00; priv->p2p.is_wilc_ie = false; eth_zero_addr(priv->associated_bss); - wilc_wlan_set_bssid(priv->dev, null_bssid, WILC_STATION_MODE); + wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE); if (!wfi_drv->p2p_connect) wlan_channel = INVALID_CHANNEL; @@ -720,13 +718,11 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, nw_info->ch, nw_info->join_params); if (ret) { - u8 null_bssid[ETH_ALEN] = {0}; - netdev_err(dev, "wilc_set_join_req(): Error\n"); ret = -ENOENT; if (!wfi_drv->p2p_connect) wlan_channel = INVALID_CHANNEL; - wilc_wlan_set_bssid(dev, null_bssid, WILC_STATION_MODE); + wilc_wlan_set_bssid(dev, NULL, WILC_STATION_MODE); goto out_error; } return 0; @@ -744,7 +740,6 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, struct wilc *wilc = vif->wilc; struct host_if_drv *wfi_drv; int ret; - u8 null_bssid[ETH_ALEN] = {0}; vif->connecting = false; @@ -760,7 +755,7 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, wfi_drv = (struct host_if_drv *)priv->hif_drv; if (!wfi_drv->p2p_connect) wlan_channel = INVALID_CHANNEL; - wilc_wlan_set_bssid(priv->dev, null_bssid, WILC_STATION_MODE); + wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE); priv->p2p.local_random = 0x01; priv->p2p.recv_random = 0x00; @@ -1805,9 +1800,8 @@ static int stop_ap(struct wiphy *wiphy, struct net_device *dev) int ret; struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(priv->dev); - u8 null_bssid[ETH_ALEN] = {0}; - wilc_wlan_set_bssid(dev, null_bssid, WILC_AP_MODE); + wilc_wlan_set_bssid(dev, NULL, WILC_AP_MODE); ret = wilc_del_beacon(vif); -- cgit From 8ffcedd6f4c2544fdb4b25479cb3d9dcd21e54e3 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 17 Jan 2019 13:21:15 +0000 Subject: staging: wilc1000: use 'struct' to pack cfg header frame in wilc_wlan_cfg_commit() Make use of 'struct' to pack cfg header in wilc_wlan_cfg_commit() instead of byte by byte filling. Signed-off-by: Ajay Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 2 +- drivers/staging/wilc1000/wilc_wlan.c | 25 ++++++++++--------------- drivers/staging/wilc1000/wilc_wlan.h | 14 ++++++++++---- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index c6685c0c238b..a3400c14c308 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -251,7 +251,7 @@ struct wilc { struct mutex cfg_cmd_lock; struct wilc_cfg_frame cfg_frame; u32 cfg_frame_offset; - int cfg_seq_no; + u8 cfg_seq_no; u8 *rx_buffer; u32 rx_buffer_offset; diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 3c5e9e030cad..16b6c5552432 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1092,24 +1092,19 @@ static int wilc_wlan_cfg_commit(struct wilc_vif *vif, int type, { 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; - int driver_handler = (u32)drv_handler; + int t_len = wilc->cfg_frame_offset + sizeof(struct wilc_cfg_cmd_hdr); if (type == WILC_CFG_SET) - cfg->wid_header[0] = 'W'; + cfg->hdr.cmd_type = 'W'; else - cfg->wid_header[0] = 'Q'; - cfg->wid_header[1] = seq_no; - cfg->wid_header[2] = (u8)total_len; - cfg->wid_header[3] = (u8)(total_len >> 8); - cfg->wid_header[4] = (u8)driver_handler; - cfg->wid_header[5] = (u8)(driver_handler >> 8); - cfg->wid_header[6] = (u8)(driver_handler >> 16); - cfg->wid_header[7] = (u8)(driver_handler >> 24); - wilc->cfg_seq_no = seq_no; - - if (!wilc_wlan_txq_add_cfg_pkt(vif, &cfg->wid_header[0], total_len)) + cfg->hdr.cmd_type = 'Q'; + + cfg->hdr.seq_no = wilc->cfg_seq_no % 256; + cfg->hdr.total_len = cpu_to_le16(t_len); + cfg->hdr.driver_handler = cpu_to_le32(drv_handler); + wilc->cfg_seq_no = cfg->hdr.seq_no; + + if (!wilc_wlan_txq_add_cfg_pkt(vif, (u8 *)&cfg->hdr, t_len)) return -1; return 0; diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 27667131de1a..c8ca13b34691 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -14,7 +14,6 @@ * Mac eth header length * ********************************************/ -#define DRIVER_HANDLER_SIZE 4 #define MAX_MAC_HDR_LEN 26 /* QOS_MAC_HDR_LEN */ #define SUB_MSDU_HEADER_LENGTH 14 #define SNAP_HDR_LEN 8 @@ -251,14 +250,21 @@ struct wilc_hif_func { #define MAX_CFG_FRAME_SIZE 1468 +struct wilc_cfg_cmd_hdr { + u8 cmd_type; + u8 seq_no; + __le16 total_len; + __le32 driver_handler; +}; + struct wilc_cfg_frame { - u8 wid_header[8]; + struct wilc_cfg_cmd_hdr hdr; u8 frame[MAX_CFG_FRAME_SIZE]; }; struct wilc_cfg_rsp { - int type; - u32 seq_no; + u8 type; + u8 seq_no; }; struct wilc; -- cgit From 6c2cfb4e87134cc7813183cf60991e981ec1a797 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 17 Jan 2019 13:21:18 +0000 Subject: staging: wilc1000: remove the use of scan shadow buffer Remove scan shadow buffer, which is used to store a copy of scan results. Instead, use cfg80211 provided API's to retrieve required info. Remove the helper functions which are operating on shadow buffer, as it's not require now. Signed-off-by: Ajay Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 94 ++---- drivers/staging/wilc1000/host_interface.h | 24 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 359 +++------------------- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 3 - 4 files changed, 86 insertions(+), 394 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a71884287fca..e7f8fabbcaae 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -210,7 +210,7 @@ static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt) scan_req = &hif_drv->usr_scan_req; if (scan_req->scan_result) { - scan_req->scan_result(evt, NULL, scan_req->arg, NULL); + scan_req->scan_result(evt, NULL, scan_req->arg); scan_req->scan_result = NULL; } @@ -564,10 +564,10 @@ out: kfree(msg); } -static void host_int_fill_join_bss_param(struct join_bss_param *param, u8 *ies, - u16 *out_index, u8 *pcipher_tc, - u8 *auth_total_cnt, u32 tsf_lo, - u8 *rates_no) +static void host_int_fill_join_bss_param(struct join_bss_param *param, + const u8 *ies, u16 *out_index, + u8 *pcipher_tc, u8 *auth_total_cnt, + u32 tsf_lo, u8 *rates_no) { u8 ext_rates_no; u16 offset; @@ -700,31 +700,44 @@ static void host_int_fill_join_bss_param(struct join_bss_param *param, u8 *ies, *out_index = index; } -static void *host_int_parse_join_bss_param(struct network_info *info) +void *wilc_parse_join_bss_param(struct cfg80211_bss *bss) { struct join_bss_param *param; u16 index = 0; u8 rates_no = 0; u8 pcipher_total_cnt = 0; u8 auth_total_cnt = 0; + const u8 *tim_elm, *ssid_elm; + const struct cfg80211_bss_ies *ies = bss->ies; param = kzalloc(sizeof(*param), GFP_KERNEL); if (!param) return NULL; - param->dtim_period = info->dtim_period; - param->beacon_period = info->beacon_period; - param->cap_info = info->cap_info; - memcpy(param->bssid, info->bssid, 6); - memcpy((u8 *)param->ssid, info->ssid, info->ssid_len + 1); - param->ssid_len = info->ssid_len; + param->beacon_period = bss->beacon_interval; + param->cap_info = bss->capability; + ether_addr_copy(param->bssid, bss->bssid); + + ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len); + if (ssid_elm) { + param->ssid_len = ssid_elm[1]; + if (param->ssid_len <= IEEE80211_MAX_SSID_LEN) + memcpy(param->ssid, ssid_elm + 2, param->ssid_len); + else + param->ssid_len = 0; + } + + tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len); + if (tim_elm && tim_elm[1] >= 2) + param->dtim_period = tim_elm[3]; + memset(param->rsn_pcip_policy, 0xFF, 3); memset(param->rsn_auth_policy, 0xFF, 3); - while (index < info->ies_len) - host_int_fill_join_bss_param(param, info->ies, &index, + while (index < ies->len) + host_int_fill_join_bss_param(param, ies->data, &index, &pcipher_total_cnt, - &auth_total_cnt, info->tsf_lo, + &auth_total_cnt, ies->tsf, &rates_no); return (void *)param; @@ -829,57 +842,20 @@ static void handle_rcvd_ntwrk_info(struct work_struct *work) struct host_if_msg *msg = container_of(work, struct host_if_msg, work); struct wilc_vif *vif = msg->vif; struct rcvd_net_info *rcvd_info = &msg->body.net_info; - u32 i; - bool found; struct network_info *info = NULL; - void *params; - struct host_if_drv *hif_drv = vif->hif_drv; - struct user_scan_req *scan_req = &hif_drv->usr_scan_req; - - found = true; + struct user_scan_req *scan_req = &vif->hif_drv->usr_scan_req; if (!scan_req->scan_result) goto done; wilc_parse_network_info(rcvd_info->buffer, &info); - if (!info || !scan_req->scan_result) { - netdev_err(vif->ndev, "%s: info or scan result NULL\n", + if (!info) { + netdev_err(vif->ndev, "%s: info is NULL\n", __func__); goto done; } - for (i = 0; i < scan_req->ch_cnt; i++) { - if (memcmp(scan_req->net_info[i].bssid, info->bssid, 6) == 0) { - if (info->rssi <= scan_req->net_info[i].rssi) { - goto done; - } else { - scan_req->net_info[i].rssi = info->rssi; - found = false; - break; - } - } - } - - if (found) { - if (scan_req->ch_cnt < MAX_NUM_SCANNED_NETWORKS) { - scan_req->net_info[scan_req->ch_cnt].rssi = info->rssi; - - memcpy(scan_req->net_info[scan_req->ch_cnt].bssid, - info->bssid, 6); - - scan_req->ch_cnt++; - - info->new_network = true; - params = host_int_parse_join_bss_param(info); - - scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info, - scan_req->arg, params); - } - } else { - info->new_network = false; - scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info, - scan_req->arg, NULL); - } + scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info, scan_req->arg); done: kfree(rcvd_info->buffer); @@ -1150,8 +1126,7 @@ int wilc_disconnect(struct wilc_vif *vif) if (scan_req->scan_result) { del_timer(&hif_drv->scan_timer); - scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg, - NULL); + scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg); scan_req->scan_result = NULL; } @@ -2131,8 +2106,7 @@ int wilc_deinit(struct wilc_vif *vif) if (hif_drv->usr_scan_req.scan_result) { hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL, - hif_drv->usr_scan_req.arg, - NULL); + hif_drv->usr_scan_req.arg); hif_drv->usr_scan_req.scan_result = NULL; } diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 9b396a79b144..6a09a52c3459 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -19,7 +19,6 @@ enum { #define WILC_MAX_NUM_STA 9 #define MAX_NUM_SCANNED_NETWORKS 100 -#define MAX_NUM_SCANNED_NETWORKS_SHADOW 130 #define WILC_MAX_NUM_PROBED_SSID 10 #define TX_MIC_KEY_LEN 8 @@ -29,8 +28,6 @@ enum { #define WILC_ADD_STA_LENGTH 40 #define WILC_NUM_CONCURRENT_IFC 2 -#define NUM_RSSI 5 - enum { WILC_SET_CFG = 0, WILC_GET_CFG @@ -38,12 +35,6 @@ enum { #define WILC_MAX_ASSOC_RESP_FRAME_SIZE 256 -struct rssi_history_buffer { - bool full; - u8 index; - s8 samples[NUM_RSSI]; -}; - struct network_info { s8 rssi; u16 cap_info; @@ -53,15 +44,9 @@ struct network_info { u16 beacon_period; u8 dtim_period; u8 ch; - unsigned long time_scan_cached; - unsigned long time_scan; - bool new_network; - u8 found; u32 tsf_lo; u8 *ies; u16 ies_len; - void *join_params; - struct rssi_history_buffer rssi_history; u64 tsf; }; @@ -129,11 +114,6 @@ enum cfg_param { WILC_CFG_PARAM_RTS_THRESHOLD = BIT(3) }; -struct found_net_info { - u8 bssid[6]; - s8 rssi; -}; - enum scan_event { SCAN_EVENT_NETWORK_FOUND = 0, SCAN_EVENT_DONE = 1, @@ -148,7 +128,7 @@ enum conn_event { }; typedef void (*wilc_scan_result)(enum scan_event, struct network_info *, - void *, void *); + void *); typedef void (*wilc_connect_result)(enum conn_event, struct connect_info *, @@ -178,7 +158,6 @@ struct user_scan_req { wilc_scan_result scan_result; void *arg; u32 ch_cnt; - struct found_net_info net_info[MAX_NUM_SCANNED_NETWORKS]; }; struct user_conn_req { @@ -307,4 +286,5 @@ int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power); void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length); void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length); void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length); +void *wilc_parse_join_bss_param(struct cfg80211_bss *bss); #endif diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 987e5ff0e44a..381dfd835181 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -29,9 +29,6 @@ #define INVALID_CHANNEL 0 -#define nl80211_SCAN_RESULT_EXPIRE (3 * HZ) -#define SCAN_RESULT_EXPIRE (40 * HZ) - static const struct ieee80211_txrx_stypes wilc_wfi_cfg80211_mgmt_types[NUM_NL80211_IFTYPES] = { [NL80211_IFTYPE_STATION] = { @@ -75,115 +72,8 @@ static u8 curr_channel; static u8 p2p_oui[] = {0x50, 0x6f, 0x9A, 0x09}; static u8 p2p_vendor_spec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03}; -#define AGING_TIME (9 * 1000) #define DURING_IP_TIME_OUT 15000 -static void clear_shadow_scan(struct wilc_priv *priv) -{ - int i; - - for (i = 0; i < priv->scanned_cnt; i++) { - kfree(priv->scanned_shadow[i].ies); - priv->scanned_shadow[i].ies = NULL; - - kfree(priv->scanned_shadow[i].join_params); - priv->scanned_shadow[i].join_params = NULL; - } - priv->scanned_cnt = 0; -} - -static u32 get_rssi_avg(struct network_info *network_info) -{ - u8 i; - int rssi_v = 0; - u8 num_rssi = (network_info->rssi_history.full) ? - NUM_RSSI : (network_info->rssi_history.index); - - for (i = 0; i < num_rssi; i++) - rssi_v += network_info->rssi_history.samples[i]; - - rssi_v /= num_rssi; - return rssi_v; -} - -static void refresh_scan(struct wilc_priv *priv, bool direct_scan) -{ - struct wiphy *wiphy = priv->dev->ieee80211_ptr->wiphy; - int i; - - for (i = 0; i < priv->scanned_cnt; i++) { - struct network_info *network_info; - s32 freq; - struct ieee80211_channel *channel; - int rssi; - struct cfg80211_bss *bss; - - network_info = &priv->scanned_shadow[i]; - - if (!memcmp("DIRECT-", network_info->ssid, 7) && !direct_scan) - continue; - - freq = ieee80211_channel_to_frequency((s32)network_info->ch, - NL80211_BAND_2GHZ); - channel = ieee80211_get_channel(wiphy, freq); - rssi = get_rssi_avg(network_info); - bss = cfg80211_inform_bss(wiphy, - channel, - CFG80211_BSS_FTYPE_UNKNOWN, - network_info->bssid, - network_info->tsf, - network_info->cap_info, - network_info->beacon_period, - (const u8 *)network_info->ies, - (size_t)network_info->ies_len, - (s32)rssi * 100, - GFP_KERNEL); - cfg80211_put_bss(wiphy, bss); - } -} - -static void reset_shadow_found(struct wilc_priv *priv) -{ - int i; - - for (i = 0; i < priv->scanned_cnt; i++) - priv->scanned_shadow[i].found = 0; -} - -static void update_scan_time(struct wilc_priv *priv) -{ - int i; - - for (i = 0; i < priv->scanned_cnt; i++) - priv->scanned_shadow[i].time_scan = jiffies; -} - -static void remove_network_from_shadow(struct timer_list *t) -{ - struct wilc_priv *priv = from_timer(priv, t, aging_timer); - unsigned long now = jiffies; - int i, j; - - for (i = 0; i < priv->scanned_cnt; i++) { - if (!time_after(now, priv->scanned_shadow[i].time_scan + - (unsigned long)(SCAN_RESULT_EXPIRE))) - continue; - kfree(priv->scanned_shadow[i].ies); - priv->scanned_shadow[i].ies = NULL; - - kfree(priv->scanned_shadow[i].join_params); - - for (j = i; (j < priv->scanned_cnt - 1); j++) - priv->scanned_shadow[j] = priv->scanned_shadow[j + 1]; - - priv->scanned_cnt--; - } - - if (priv->scanned_cnt != 0) - mod_timer(&priv->aging_timer, - jiffies + msecs_to_jiffies(AGING_TIME)); -} - static void clear_during_ip(struct timer_list *t) { struct wilc_vif *vif = from_timer(vif, t, during_ip_timer); @@ -191,87 +81,15 @@ static void clear_during_ip(struct timer_list *t) vif->obtaining_ip = false; } -static int is_network_in_shadow(struct network_info *nw_info, - struct wilc_priv *priv) -{ - int state = -1; - int i; - - if (priv->scanned_cnt == 0) { - mod_timer(&priv->aging_timer, - jiffies + msecs_to_jiffies(AGING_TIME)); - state = -1; - } else { - for (i = 0; i < priv->scanned_cnt; i++) { - if (memcmp(priv->scanned_shadow[i].bssid, - nw_info->bssid, 6) == 0) { - state = i; - break; - } - } - } - return state; -} - -static void add_network_to_shadow(struct network_info *nw_info, - struct wilc_priv *priv, void *join_params) -{ - int ap_found = is_network_in_shadow(nw_info, priv); - u32 ap_index = 0; - u8 rssi_index = 0; - struct network_info *shadow_nw_info; - - if (priv->scanned_cnt >= MAX_NUM_SCANNED_NETWORKS_SHADOW) - return; - - if (ap_found == -1) { - ap_index = priv->scanned_cnt; - priv->scanned_cnt++; - } else { - ap_index = ap_found; - } - shadow_nw_info = &priv->scanned_shadow[ap_index]; - rssi_index = shadow_nw_info->rssi_history.index; - shadow_nw_info->rssi_history.samples[rssi_index++] = nw_info->rssi; - if (rssi_index == NUM_RSSI) { - rssi_index = 0; - shadow_nw_info->rssi_history.full = true; - } - shadow_nw_info->rssi_history.index = rssi_index; - shadow_nw_info->rssi = nw_info->rssi; - shadow_nw_info->cap_info = nw_info->cap_info; - shadow_nw_info->ssid_len = nw_info->ssid_len; - memcpy(shadow_nw_info->ssid, nw_info->ssid, nw_info->ssid_len); - memcpy(shadow_nw_info->bssid, nw_info->bssid, ETH_ALEN); - shadow_nw_info->beacon_period = nw_info->beacon_period; - shadow_nw_info->dtim_period = nw_info->dtim_period; - shadow_nw_info->ch = nw_info->ch; - shadow_nw_info->tsf = nw_info->tsf; - if (ap_found != -1) - kfree(shadow_nw_info->ies); - shadow_nw_info->ies = kmemdup(nw_info->ies, nw_info->ies_len, - GFP_KERNEL); - if (shadow_nw_info->ies) - shadow_nw_info->ies_len = nw_info->ies_len; - else - shadow_nw_info->ies_len = 0; - shadow_nw_info->time_scan = jiffies; - shadow_nw_info->time_scan_cached = jiffies; - shadow_nw_info->found = 1; - if (ap_found != -1) - kfree(shadow_nw_info->join_params); - shadow_nw_info->join_params = join_params; -} - static void cfg_scan_result(enum scan_event scan_event, struct network_info *network_info, - void *user_void, void *join_params) + void *user_void) { struct wilc_priv *priv; struct wiphy *wiphy; s32 freq; struct ieee80211_channel *channel; - struct cfg80211_bss *bss = NULL; + struct cfg80211_bss *bss; priv = user_void; if (!priv->cfg_scanning) @@ -291,51 +109,22 @@ static void cfg_scan_result(enum scan_event scan_event, freq = ieee80211_channel_to_frequency((s32)network_info->ch, NL80211_BAND_2GHZ); channel = ieee80211_get_channel(wiphy, freq); - if (!channel) return; - if (network_info->new_network) { - if (priv->rcvd_ch_cnt >= MAX_NUM_SCANNED_NETWORKS) - return; - - priv->rcvd_ch_cnt++; - - add_network_to_shadow(network_info, priv, join_params); - - if (memcmp("DIRECT-", network_info->ssid, 7)) - return; - - bss = cfg80211_inform_bss(wiphy, - channel, - CFG80211_BSS_FTYPE_UNKNOWN, - network_info->bssid, - network_info->tsf, - network_info->cap_info, - network_info->beacon_period, - (const u8 *)network_info->ies, - (size_t)network_info->ies_len, - (s32)network_info->rssi * 100, - GFP_KERNEL); - cfg80211_put_bss(wiphy, bss); - } else { - u32 i; - - for (i = 0; i < priv->rcvd_ch_cnt; i++) { - if (memcmp(priv->scanned_shadow[i].bssid, - network_info->bssid, 6) == 0) - break; - } - - if (i >= priv->rcvd_ch_cnt) - return; - - priv->scanned_shadow[i].rssi = network_info->rssi; - priv->scanned_shadow[i].time_scan = jiffies; - } + bss = cfg80211_inform_bss(wiphy, + channel, + CFG80211_BSS_FTYPE_UNKNOWN, + network_info->bssid, + network_info->tsf, + network_info->cap_info, + network_info->beacon_period, + (const u8 *)network_info->ies, + (size_t)network_info->ies_len, + (s32)network_info->rssi * 100, + GFP_KERNEL); + cfg80211_put_bss(wiphy, bss); } else if (scan_event == SCAN_EVENT_DONE) { - refresh_scan(priv, false); - mutex_lock(&priv->scan_req_lock); if (priv->scan_req) { @@ -344,7 +133,6 @@ static void cfg_scan_result(enum scan_event scan_event, }; cfg80211_scan_done(priv->scan_req, &info); - priv->rcvd_ch_cnt = 0; priv->cfg_scanning = false; priv->scan_req = NULL; } @@ -357,9 +145,6 @@ static void cfg_scan_result(enum scan_event scan_event, .aborted = false, }; - update_scan_time(priv); - refresh_scan(priv, false); - cfg80211_scan_done(priv->scan_req, &info); priv->cfg_scanning = false; priv->scan_req = NULL; @@ -368,17 +153,6 @@ static void cfg_scan_result(enum scan_event scan_event, } } -static inline bool wilc_cfg_scan_time_expired(struct wilc_priv *priv, int i) -{ - unsigned long now = jiffies; - - if (time_after(now, priv->scanned_shadow[i].time_scan_cached + - (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ)))) - return true; - else - return false; -} - static void cfg_connect_result(enum conn_event conn_disconn_evt, struct connect_info *conn_info, u8 mac_status, @@ -409,28 +183,10 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, netdev_err(dev, "Unspecified failure\n"); } - if (connect_status == WLAN_STATUS_SUCCESS) { - bool scan_refresh = false; - u32 i; - + if (connect_status == WLAN_STATUS_SUCCESS) memcpy(priv->associated_bss, conn_info->bssid, ETH_ALEN); - for (i = 0; i < priv->scanned_cnt; i++) { - if (memcmp(priv->scanned_shadow[i].bssid, - conn_info->bssid, - ETH_ALEN) == 0) { - if (wilc_cfg_scan_time_expired(priv, i)) - scan_refresh = true; - - break; - } - } - - if (scan_refresh) - refresh_scan(priv, true); - } - cfg80211_connect_result(dev, conn_info->bssid, conn_info->req_ies, conn_info->req_ies_len, @@ -531,10 +287,6 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) priv->scan_req = request; - priv->rcvd_ch_cnt = 0; - - reset_shadow_found(priv); - priv->cfg_scanning = true; if (request->n_channels <= MAX_NUM_SCANNED_NETWORKS) { for (i = 0; i < request->n_channels; i++) { @@ -583,13 +335,13 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(priv->dev); struct host_if_drv *wfi_drv = priv->hif_drv; - struct network_info *nw_info; int ret; u32 i; - u32 sel_bssi_idx = UINT_MAX; u8 security = WILC_FW_SEC_NO; enum authtype auth_type = WILC_FW_AUTH_ANY; u32 cipher_group; + struct cfg80211_bss *bss; + void *join_params; vif->connecting = true; @@ -598,39 +350,6 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, else wfi_drv->p2p_connect = 0; - for (i = 0; i < priv->scanned_cnt; i++) { - if (sme->ssid_len == priv->scanned_shadow[i].ssid_len && - memcmp(priv->scanned_shadow[i].ssid, - sme->ssid, - sme->ssid_len) == 0) { - if (!sme->bssid) { - if (sel_bssi_idx == UINT_MAX || - priv->scanned_shadow[i].rssi > - priv->scanned_shadow[sel_bssi_idx].rssi) - sel_bssi_idx = i; - } else { - if (memcmp(priv->scanned_shadow[i].bssid, - sme->bssid, - ETH_ALEN) == 0) { - sel_bssi_idx = i; - break; - } - } - } - } - - if (sel_bssi_idx < priv->scanned_cnt) { - nw_info = &priv->scanned_shadow[sel_bssi_idx]; - } else { - ret = -ENOENT; - goto out_error; - } - - if (ether_addr_equal_unaligned(vif->bssid, nw_info->bssid)) { - ret = -EALREADY; - goto out_error; - } - memset(priv->wep_key, 0, sizeof(priv->wep_key)); memset(priv->wep_key_len, 0, sizeof(priv->wep_key_len)); @@ -704,29 +423,54 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, auth_type = WILC_FW_AUTH_IEEE8021; } - curr_channel = nw_info->ch; + bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, sme->ssid, + sme->ssid_len, IEEE80211_BSS_TYPE_ANY, + IEEE80211_PRIVACY(sme->privacy)); + if (!bss) { + ret = -EINVAL; + goto out_error; + } + + if (ether_addr_equal_unaligned(vif->bssid, bss->bssid)) { + ret = -EALREADY; + goto out_put_bss; + } + + join_params = wilc_parse_join_bss_param(bss); + if (!join_params) { + netdev_err(dev, "%s: failed to construct join param\n", + __func__); + ret = -EINVAL; + goto out_put_bss; + } + + curr_channel = ieee80211_frequency_to_channel(bss->channel->center_freq); if (!wfi_drv->p2p_connect) - wlan_channel = nw_info->ch; + wlan_channel = curr_channel; - wilc_wlan_set_bssid(dev, nw_info->bssid, WILC_STATION_MODE); + wilc_wlan_set_bssid(dev, bss->bssid, WILC_STATION_MODE); - ret = wilc_set_join_req(vif, nw_info->bssid, sme->ssid, + ret = wilc_set_join_req(vif, bss->bssid, sme->ssid, sme->ssid_len, sme->ie, sme->ie_len, cfg_connect_result, (void *)priv, - security, auth_type, - nw_info->ch, - nw_info->join_params); + security, auth_type, curr_channel, join_params); if (ret) { netdev_err(dev, "wilc_set_join_req(): Error\n"); ret = -ENOENT; if (!wfi_drv->p2p_connect) wlan_channel = INVALID_CHANNEL; wilc_wlan_set_bssid(dev, NULL, WILC_STATION_MODE); - goto out_error; + kfree(join_params); + goto out_put_bss; } + kfree(join_params); + cfg80211_put_bss(wiphy, bss); return 0; +out_put_bss: + cfg80211_put_bss(wiphy, bss); + out_error: vif->connecting = false; return ret; @@ -2096,7 +1840,6 @@ int wilc_init_host_int(struct net_device *net) struct wilc_priv *priv = wdev_priv(net->ieee80211_ptr); struct wilc_vif *vif = netdev_priv(priv->dev); - timer_setup(&priv->aging_timer, remove_network_from_shadow, 0); timer_setup(&vif->during_ip_timer, clear_during_ip, 0); priv->p2p_listen_state = false; @@ -2120,8 +1863,6 @@ void wilc_deinit_host_int(struct net_device *net) mutex_destroy(&priv->scan_req_lock); ret = wilc_deinit(vif); - del_timer_sync(&priv->aging_timer); - clear_shadow_scan(priv); del_timer_sync(&vif->during_ip_timer); if (ret) diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index a3400c14c308..59e835259a83 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -137,7 +137,6 @@ struct wilc_priv { u64 tx_cookie; bool cfg_scanning; - u32 rcvd_ch_cnt; u8 associated_bss[ETH_ALEN]; struct sta_info assoc_stainfo; @@ -155,8 +154,6 @@ struct wilc_priv { /* mutexes */ struct mutex scan_req_lock; bool p2p_listen_state; - struct timer_list aging_timer; - struct network_info scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW]; int scanned_cnt; struct wilc_p2p_var p2p; -- cgit From 6cd4fa5ab6913ab8a9a35970b8c70e759c3e68cf Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 17 Jan 2019 13:21:21 +0000 Subject: staging: wilc1000: make use of cfg80211_inform_bss_frame() Use cfg80211_inform_bss_frame() api instead of cfg80211_inform_bss() to inform cfg80211 about the BSS frame, to avoid unnecessary parsing of frame in driver. Signed-off-by: Ajay Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 144 +++++----------------- drivers/staging/wilc1000/host_interface.h | 14 ++- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 42 +++---- 3 files changed, 50 insertions(+), 150 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index e7f8fabbcaae..68f58d11ec52 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -72,7 +72,7 @@ struct wilc_gtk_key { } __packed; union message_body { - struct rcvd_net_info net_info; + struct wilc_rcvd_net_info net_info; struct rcvd_async_info async_info; struct set_multicast multicast_info; struct remain_ch remain_on_ch; @@ -743,129 +743,38 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss) return (void *)param; } -static inline u8 *get_bssid(struct ieee80211_mgmt *mgmt) -{ - if (ieee80211_has_fromds(mgmt->frame_control)) - return mgmt->sa; - else if (ieee80211_has_tods(mgmt->frame_control)) - return mgmt->da; - else - return mgmt->bssid; -} - -static s32 wilc_parse_network_info(u8 *msg_buffer, - struct network_info **ret_network_info) +static void handle_rcvd_ntwrk_info(struct work_struct *work) { - struct network_info *info; - struct ieee80211_mgmt *mgt; - u8 *wid_val, *ies; - u16 wid_len, rx_len, ies_len; - u8 msg_type; + struct host_if_msg *msg = container_of(work, struct host_if_msg, work); + struct wilc_rcvd_net_info *rcvd_info = &msg->body.net_info; + struct user_scan_req *scan_req = &msg->vif->hif_drv->usr_scan_req; + const u8 *ch_elm; + u8 *ies; + int ies_len; size_t offset; - const u8 *ch_elm, *tim_elm, *ssid_elm; - - msg_type = msg_buffer[0]; - if ('N' != msg_type) - return -EFAULT; - - wid_len = get_unaligned_le16(&msg_buffer[6]); - wid_val = &msg_buffer[8]; - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - info->rssi = wid_val[0]; - - mgt = (struct ieee80211_mgmt *)&wid_val[1]; - rx_len = wid_len - 1; - - if (ieee80211_is_probe_resp(mgt->frame_control)) { - info->cap_info = le16_to_cpu(mgt->u.probe_resp.capab_info); - info->beacon_period = le16_to_cpu(mgt->u.probe_resp.beacon_int); - info->tsf = le64_to_cpu(mgt->u.probe_resp.timestamp); - info->tsf_lo = (u32)info->tsf; + if (ieee80211_is_probe_resp(rcvd_info->mgmt->frame_control)) offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - } else if (ieee80211_is_beacon(mgt->frame_control)) { - info->cap_info = le16_to_cpu(mgt->u.beacon.capab_info); - info->beacon_period = le16_to_cpu(mgt->u.beacon.beacon_int); - info->tsf = le64_to_cpu(mgt->u.beacon.timestamp); - info->tsf_lo = (u32)info->tsf; + else if (ieee80211_is_beacon(rcvd_info->mgmt->frame_control)) offset = offsetof(struct ieee80211_mgmt, u.beacon.variable); - } else { - /* only process probe response and beacon frame */ - kfree(info); - return -EIO; - } - - ether_addr_copy(info->bssid, get_bssid(mgt)); - - ies = mgt->u.beacon.variable; - ies_len = rx_len - offset; - if (ies_len <= 0) { - kfree(info); - return -EIO; - } - - info->ies = kmemdup(ies, ies_len, GFP_KERNEL); - if (!info->ies) { - kfree(info); - return -ENOMEM; - } - - info->ies_len = ies_len; + else + goto done; - ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies, ies_len); - if (ssid_elm) { - info->ssid_len = ssid_elm[1]; - if (info->ssid_len <= IEEE80211_MAX_SSID_LEN) - memcpy(info->ssid, ssid_elm + 2, info->ssid_len); - else - info->ssid_len = 0; - } + ies = rcvd_info->mgmt->u.beacon.variable; + ies_len = rcvd_info->frame_len - offset; + if (ies_len <= 0) + goto done; ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len); if (ch_elm && ch_elm[1] > 0) - info->ch = ch_elm[2]; - - tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies, ies_len); - if (tim_elm && tim_elm[1] >= 2) - info->dtim_period = tim_elm[3]; - - *ret_network_info = info; - - return 0; -} - -static void handle_rcvd_ntwrk_info(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct rcvd_net_info *rcvd_info = &msg->body.net_info; - struct network_info *info = NULL; - struct user_scan_req *scan_req = &vif->hif_drv->usr_scan_req; - - if (!scan_req->scan_result) - goto done; + rcvd_info->ch = ch_elm[2]; - wilc_parse_network_info(rcvd_info->buffer, &info); - if (!info) { - netdev_err(vif->ndev, "%s: info is NULL\n", - __func__); - goto done; - } - - scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info, scan_req->arg); + if (scan_req->scan_result) + scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, rcvd_info, + scan_req->arg); done: - kfree(rcvd_info->buffer); - rcvd_info->buffer = NULL; - - if (info) { - kfree(info->ies); - kfree(info); - } - + kfree(rcvd_info->mgmt); kfree(msg); } @@ -2143,9 +2052,12 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length) if (IS_ERR(msg)) return; - msg->body.net_info.len = length; - msg->body.net_info.buffer = kmemdup(buffer, length, GFP_KERNEL); - if (!msg->body.net_info.buffer) { + msg->body.net_info.frame_len = get_unaligned_le16(&buffer[6]) - 1; + msg->body.net_info.rssi = buffer[8]; + msg->body.net_info.mgmt = kmemdup(&buffer[9], + msg->body.net_info.frame_len, + GFP_KERNEL); + if (!msg->body.net_info.mgmt) { kfree(msg); return; } @@ -2153,7 +2065,7 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length) result = wilc_enqueue_work(msg); if (result) { netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg->body.net_info.buffer); + kfree(msg->body.net_info.mgmt); kfree(msg); } } diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 6a09a52c3459..76da17267e24 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -127,7 +127,14 @@ enum conn_event { CONN_DISCONN_EVENT_FORCE_32BIT = 0xFFFFFFFF }; -typedef void (*wilc_scan_result)(enum scan_event, struct network_info *, +struct wilc_rcvd_net_info { + s8 rssi; + u8 ch; + u16 frame_len; + struct ieee80211_mgmt *mgmt; +}; + +typedef void (*wilc_scan_result)(enum scan_event, struct wilc_rcvd_net_info *, void *); typedef void (*wilc_connect_result)(enum conn_event, @@ -139,11 +146,6 @@ typedef void (*wilc_connect_result)(enum conn_event, typedef void (*wilc_remain_on_chan_expired)(void *, u32); typedef void (*wilc_remain_on_chan_ready)(void *); -struct rcvd_net_info { - u8 *buffer; - u32 len; -}; - struct hidden_net_info { u8 *ssid; u8 ssid_len; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 381dfd835181..5da03bb88ab4 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -82,48 +82,34 @@ static void clear_during_ip(struct timer_list *t) } static void cfg_scan_result(enum scan_event scan_event, - struct network_info *network_info, - void *user_void) + struct wilc_rcvd_net_info *info, void *user_void) { - struct wilc_priv *priv; - struct wiphy *wiphy; - s32 freq; - struct ieee80211_channel *channel; - struct cfg80211_bss *bss; + struct wilc_priv *priv = user_void; - priv = user_void; if (!priv->cfg_scanning) return; if (scan_event == SCAN_EVENT_NETWORK_FOUND) { - wiphy = priv->dev->ieee80211_ptr->wiphy; - - if (!wiphy || !network_info) - return; + s32 freq; + struct ieee80211_channel *channel; + struct cfg80211_bss *bss; + struct wiphy *wiphy = priv->dev->ieee80211_ptr->wiphy; - if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && - (((s32)network_info->rssi * 100) < 0 || - ((s32)network_info->rssi * 100) > 100)) + if (!wiphy || !info) return; - freq = ieee80211_channel_to_frequency((s32)network_info->ch, + freq = ieee80211_channel_to_frequency((s32)info->ch, NL80211_BAND_2GHZ); channel = ieee80211_get_channel(wiphy, freq); if (!channel) return; - bss = cfg80211_inform_bss(wiphy, - channel, - CFG80211_BSS_FTYPE_UNKNOWN, - network_info->bssid, - network_info->tsf, - network_info->cap_info, - network_info->beacon_period, - (const u8 *)network_info->ies, - (size_t)network_info->ies_len, - (s32)network_info->rssi * 100, - GFP_KERNEL); - cfg80211_put_bss(wiphy, bss); + bss = cfg80211_inform_bss_frame(wiphy, channel, info->mgmt, + info->frame_len, + (s32)info->rssi * 100, + GFP_KERNEL); + if (!bss) + cfg80211_put_bss(wiphy, bss); } else if (scan_event == SCAN_EVENT_DONE) { mutex_lock(&priv->scan_req_lock); -- cgit From dc18fa1de9acc57d599c50437fc04a5a08e19b82 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 17 Jan 2019 13:21:24 +0000 Subject: staging: wilc1000: corrected order to pack join param buffer Modified packing order for join param as expected by firmware. Signed-off-by: Ajay Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 68f58d11ec52..2fb56975ccc3 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -11,8 +11,6 @@ #define FALSE_FRMWR_CHANNEL 100 -#define REAL_JOIN_REQ 0 - struct rcvd_async_info { u8 *buffer; u32 len; @@ -436,15 +434,14 @@ static int wilc_send_connect_wid(struct wilc_vif *vif) memcpy(cur_byte, bss_param->rsn_cap, sizeof(bss_param->rsn_cap)); cur_byte += sizeof(bss_param->rsn_cap); - *(cur_byte++) = REAL_JOIN_REQ; *(cur_byte++) = bss_param->noa_enabled; if (bss_param->noa_enabled) { put_unaligned_le32(bss_param->tsf, cur_byte); cur_byte += 4; - *(cur_byte++) = bss_param->opp_enabled; *(cur_byte++) = bss_param->idx; + *(cur_byte++) = bss_param->opp_enabled; if (bss_param->opp_enabled) *(cur_byte++) = bss_param->ct_window; -- cgit From 4e0b0f42c9c7cbb756aee9e418f7ad15cdf16cd6 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 17 Jan 2019 13:21:27 +0000 Subject: staging: wilc1000: use struct to pack join parameters for FW Refactor code to use struct to construct the join parameters. Avoid use of extra buffer before sending to FW instead directly pass the struct pointer. Signed-off-by: Ajay Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 404 ++++++++-------------- drivers/staging/wilc1000/host_interface.h | 18 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- drivers/staging/wilc1000/wilc_wlan_if.h | 1 - 4 files changed, 142 insertions(+), 283 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 2fb56975ccc3..46fd448ddde7 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -86,34 +86,50 @@ struct host_if_msg { bool is_sync; }; -struct join_bss_param { - enum bss_types bss_type; +struct wilc_noa_opp_enable { + u8 ct_window; + u8 cnt; + __le32 duration; + __le32 interval; + __le32 start_time; +} __packed; + +struct wilc_noa_opp_disable { + u8 cnt; + __le32 duration; + __le32 interval; + __le32 start_time; +} __packed; + +struct wilc_join_bss_param { + char ssid[IEEE80211_MAX_SSID_LEN]; + u8 ssid_terminator; + u8 bss_type; + u8 ch; + __le16 cap_info; + u8 sa[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + __le16 beacon_period; u8 dtim_period; - u16 beacon_period; - u16 cap_info; - u8 bssid[6]; - char ssid[MAX_SSID_LEN]; - u8 ssid_len; u8 supp_rates[MAX_RATES_SUPPORTED + 1]; - u8 ht_capable; u8 wmm_cap; u8 uapsd_cap; - bool rsn_found; + u8 ht_capable; + u8 rsn_found; u8 rsn_grp_policy; u8 mode_802_11i; - u8 rsn_pcip_policy[3]; - u8 rsn_auth_policy[3]; + u8 p_suites[3]; + u8 akm_suites[3]; u8 rsn_cap[2]; - u32 tsf; u8 noa_enabled; - u8 opp_enabled; - u8 ct_window; - u8 cnt; + __le32 tsf_lo; u8 idx; - u8 duration[4]; - u8 interval[4]; - u8 start_time[4]; -}; + u8 opp_enabled; + union { + struct wilc_noa_opp_disable opp_dis; + struct wilc_noa_opp_enable opp_en; + }; +} __packed; static struct host_if_drv *terminated_handle; static struct mutex hif_deinit_lock; @@ -329,10 +345,9 @@ static int wilc_send_connect_wid(struct wilc_vif *vif) int result = 0; struct wid wid_list[8]; u32 wid_cnt = 0, dummyval = 0; - u8 *cur_byte = NULL; struct host_if_drv *hif_drv = vif->hif_drv; struct user_conn_req *conn_attr = &hif_drv->usr_conn_req; - struct join_bss_param *bss_param = hif_drv->usr_conn_req.param; + struct wilc_join_bss_param *bss_param = hif_drv->usr_conn_req.param; wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT; wid_list[wid_cnt].type = WID_INT; @@ -372,96 +387,8 @@ static int wilc_send_connect_wid(struct wilc_vif *vif) wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED; wid_list[wid_cnt].type = WID_STR; - wid_list[wid_cnt].size = 112; - wid_list[wid_cnt].val = kmalloc(wid_list[wid_cnt].size, GFP_KERNEL); - - if (!wid_list[wid_cnt].val) { - result = -EFAULT; - goto error; - } - - cur_byte = wid_list[wid_cnt].val; - - if (conn_attr->ssid) { - memcpy(cur_byte, conn_attr->ssid, conn_attr->ssid_len); - cur_byte[conn_attr->ssid_len] = '\0'; - } - cur_byte += MAX_SSID_LEN; - *(cur_byte++) = WILC_FW_BSS_TYPE_INFRA; - - if (conn_attr->ch >= 1 && conn_attr->ch <= 14) { - *(cur_byte++) = conn_attr->ch; - } else { - netdev_err(vif->ndev, "Channel out of range\n"); - *(cur_byte++) = 0xFF; - } - put_unaligned_le16(bss_param->cap_info, cur_byte); - cur_byte += 2; - - if (conn_attr->bssid) - memcpy(cur_byte, conn_attr->bssid, 6); - cur_byte += 6; - - if (conn_attr->bssid) - memcpy(cur_byte, conn_attr->bssid, 6); - cur_byte += 6; - - put_unaligned_le16(bss_param->beacon_period, cur_byte); - cur_byte += 2; - *(cur_byte++) = bss_param->dtim_period; - - memcpy(cur_byte, bss_param->supp_rates, MAX_RATES_SUPPORTED + 1); - cur_byte += (MAX_RATES_SUPPORTED + 1); - - *(cur_byte++) = bss_param->wmm_cap; - *(cur_byte++) = bss_param->uapsd_cap; - - *(cur_byte++) = bss_param->ht_capable; - conn_attr->ht_capable = bss_param->ht_capable; - - *(cur_byte++) = bss_param->rsn_found; - *(cur_byte++) = bss_param->rsn_grp_policy; - *(cur_byte++) = bss_param->mode_802_11i; - - memcpy(cur_byte, bss_param->rsn_pcip_policy, - sizeof(bss_param->rsn_pcip_policy)); - cur_byte += sizeof(bss_param->rsn_pcip_policy); - - memcpy(cur_byte, bss_param->rsn_auth_policy, - sizeof(bss_param->rsn_auth_policy)); - cur_byte += sizeof(bss_param->rsn_auth_policy); - - memcpy(cur_byte, bss_param->rsn_cap, sizeof(bss_param->rsn_cap)); - cur_byte += sizeof(bss_param->rsn_cap); - - *(cur_byte++) = bss_param->noa_enabled; - - if (bss_param->noa_enabled) { - put_unaligned_le32(bss_param->tsf, cur_byte); - cur_byte += 4; - - *(cur_byte++) = bss_param->idx; - *(cur_byte++) = bss_param->opp_enabled; - - if (bss_param->opp_enabled) - *(cur_byte++) = bss_param->ct_window; - - *(cur_byte++) = bss_param->cnt; - - memcpy(cur_byte, bss_param->duration, - sizeof(bss_param->duration)); - cur_byte += sizeof(bss_param->duration); - - memcpy(cur_byte, bss_param->interval, - sizeof(bss_param->interval)); - cur_byte += sizeof(bss_param->interval); - - memcpy(cur_byte, bss_param->start_time, - sizeof(bss_param->start_time)); - cur_byte += sizeof(bss_param->start_time); - } - - cur_byte = wid_list[wid_cnt].val; + wid_list[wid_cnt].size = sizeof(*bss_param); + wid_list[wid_cnt].val = (u8 *)bss_param; wid_cnt++; result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, @@ -469,13 +396,11 @@ static int wilc_send_connect_wid(struct wilc_vif *vif) wilc_get_vif_idx(vif)); if (result) { netdev_err(vif->ndev, "failed to send config packet\n"); - kfree(cur_byte); goto error; } else { hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP; } - kfree(cur_byte); return 0; error: @@ -561,181 +486,130 @@ out: kfree(msg); } -static void host_int_fill_join_bss_param(struct join_bss_param *param, - const u8 *ies, u16 *out_index, - u8 *pcipher_tc, u8 *auth_total_cnt, - u32 tsf_lo, u8 *rates_no) +void *wilc_parse_join_bss_param(struct cfg80211_bss *bss, + struct cfg80211_crypto_settings *crypto) { - u8 ext_rates_no; - u16 offset; - u8 pcipher_cnt; - u8 auth_cnt; - u8 i, j; - u16 index = *out_index; - - if (ies[index] == WLAN_EID_SUPP_RATES) { - *rates_no = ies[index + 1]; - param->supp_rates[0] = *rates_no; - index += 2; + struct wilc_join_bss_param *param; + struct ieee80211_p2p_noa_attr noa_attr; + u8 rates_len = 0; + const u8 *tim_elm, *ssid_elm, *rates_ie, *supp_rates_ie; + const u8 *ht_ie, *wpa_ie, *wmm_ie, *rsn_ie; + int ret; + const struct cfg80211_bss_ies *ies = bss->ies; - for (i = 0; i < *rates_no; i++) - param->supp_rates[i + 1] = ies[index + i]; + param = kzalloc(sizeof(*param), GFP_KERNEL); + if (!param) + return NULL; - index += *rates_no; - } else if (ies[index] == WLAN_EID_EXT_SUPP_RATES) { - ext_rates_no = ies[index + 1]; - if (ext_rates_no > (MAX_RATES_SUPPORTED - *rates_no)) - param->supp_rates[0] = MAX_RATES_SUPPORTED; - else - param->supp_rates[0] += ext_rates_no; - index += 2; - for (i = 0; i < (param->supp_rates[0] - *rates_no); i++) - param->supp_rates[*rates_no + i + 1] = ies[index + i]; + param->beacon_period = bss->beacon_interval; + param->cap_info = bss->capability; + param->bss_type = WILC_FW_BSS_TYPE_INFRA; + param->ch = ieee80211_frequency_to_channel(bss->channel->center_freq); + ether_addr_copy(param->bssid, bss->bssid); - index += ext_rates_no; - } else if (ies[index] == WLAN_EID_HT_CAPABILITY) { - param->ht_capable = true; - index += ies[index + 1] + 2; - } else if ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) && - (ies[index + 2] == 0x00) && (ies[index + 3] == 0x50) && - (ies[index + 4] == 0xF2) && (ies[index + 5] == 0x02) && - ((ies[index + 6] == 0x00) || (ies[index + 6] == 0x01)) && - (ies[index + 7] == 0x01)) { - param->wmm_cap = true; - - if (ies[index + 8] & BIT(7)) - param->uapsd_cap = true; - index += ies[index + 1] + 2; - } else if ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) && - (ies[index + 2] == 0x50) && (ies[index + 3] == 0x6f) && - (ies[index + 4] == 0x9a) && - (ies[index + 5] == 0x09) && (ies[index + 6] == 0x0c)) { - u16 p2p_cnt; - - param->tsf = tsf_lo; - param->noa_enabled = 1; - param->idx = ies[index + 9]; + ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len); + if (ssid_elm) { + if (ssid_elm[1] <= IEEE80211_MAX_SSID_LEN) + memcpy(param->ssid, ssid_elm + 2, ssid_elm[1]); + } - if (ies[index + 10] & BIT(7)) { - param->opp_enabled = 1; - param->ct_window = ies[index + 10]; - } else { - param->opp_enabled = 0; - } + tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len); + if (tim_elm && tim_elm[1] >= 2) + param->dtim_period = tim_elm[3]; - param->cnt = ies[index + 11]; - p2p_cnt = index + 12; + memset(param->p_suites, 0xFF, 3); + memset(param->akm_suites, 0xFF, 3); - memcpy(param->duration, ies + p2p_cnt, 4); - p2p_cnt += 4; + rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies->data, ies->len); + if (rates_ie) { + rates_len = rates_ie[1]; + param->supp_rates[0] = rates_len; + memcpy(¶m->supp_rates[1], rates_ie + 2, rates_len); + } - memcpy(param->interval, ies + p2p_cnt, 4); - p2p_cnt += 4; + supp_rates_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, ies->data, + ies->len); + if (supp_rates_ie) { + if (supp_rates_ie[1] > (MAX_RATES_SUPPORTED - rates_len)) + param->supp_rates[0] = MAX_RATES_SUPPORTED; + else + param->supp_rates[0] += supp_rates_ie[1]; - memcpy(param->start_time, ies + p2p_cnt, 4); + memcpy(¶m->supp_rates[rates_len + 1], supp_rates_ie + 2, + (param->supp_rates[0] - rates_len)); + } - index += ies[index + 1] + 2; - } else if ((ies[index] == WLAN_EID_RSN) || - ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) && - (ies[index + 2] == 0x00) && - (ies[index + 3] == 0x50) && (ies[index + 4] == 0xF2) && - (ies[index + 5] == 0x01))) { - u16 rsn_idx = index; + ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies->data, ies->len); + if (ht_ie) + param->ht_capable = true; - if (ies[rsn_idx] == WLAN_EID_RSN) { - param->mode_802_11i = 2; + ret = cfg80211_get_p2p_attr(ies->data, ies->len, + IEEE80211_P2P_ATTR_ABSENCE_NOTICE, + (u8 *)&noa_attr, sizeof(noa_attr)); + if (ret > 0) { + param->tsf_lo = cpu_to_le32(ies->tsf); + param->noa_enabled = 1; + param->idx = noa_attr.index; + if (noa_attr.oppps_ctwindow & IEEE80211_P2P_OPPPS_ENABLE_BIT) { + param->opp_enabled = 1; + param->opp_en.ct_window = noa_attr.oppps_ctwindow; + param->opp_en.cnt = noa_attr.desc[0].count; + param->opp_en.duration = noa_attr.desc[0].duration; + param->opp_en.interval = noa_attr.desc[0].interval; + param->opp_en.start_time = noa_attr.desc[0].start_time; } else { - if (param->mode_802_11i == 0) - param->mode_802_11i = 1; - rsn_idx += 4; - } - - rsn_idx += 7; - param->rsn_grp_policy = ies[rsn_idx]; - rsn_idx++; - offset = ies[rsn_idx] * 4; - pcipher_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx]; - rsn_idx += 2; - - i = *pcipher_tc; - j = 0; - for (; i < (pcipher_cnt + *pcipher_tc) && i < 3; i++, j++) { - u8 *policy = ¶m->rsn_pcip_policy[i]; - - *policy = ies[rsn_idx + ((j + 1) * 4) - 1]; + param->opp_enabled = 0; + param->opp_dis.cnt = noa_attr.desc[0].count; + param->opp_dis.duration = noa_attr.desc[0].duration; + param->opp_dis.interval = noa_attr.desc[0].interval; + param->opp_dis.start_time = noa_attr.desc[0].start_time; } - - *pcipher_tc += pcipher_cnt; - rsn_idx += offset; - - offset = ies[rsn_idx] * 4; - - auth_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx]; - rsn_idx += 2; - i = *auth_total_cnt; - j = 0; - for (; i < (*auth_total_cnt + auth_cnt); i++, j++) { - u8 *policy = ¶m->rsn_auth_policy[i]; - - *policy = ies[rsn_idx + ((j + 1) * 4) - 1]; + } + wmm_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WMM, + ies->data, ies->len); + if (wmm_ie) { + struct ieee80211_wmm_param_ie *ie; + + ie = (struct ieee80211_wmm_param_ie *)wmm_ie; + if ((ie->oui_subtype == 0 || ie->oui_subtype == 1) && + ie->version == 1) { + param->wmm_cap = true; + if (ie->qos_info & BIT(7)) + param->uapsd_cap = true; } + } - *auth_total_cnt += auth_cnt; - rsn_idx += offset; - - if (ies[index] == WLAN_EID_RSN) { - param->rsn_cap[0] = ies[rsn_idx]; - param->rsn_cap[1] = ies[rsn_idx + 1]; - rsn_idx += 2; - } + wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPA, + ies->data, ies->len); + if (wpa_ie) { + param->mode_802_11i = 1; param->rsn_found = true; - index += ies[index + 1] + 2; - } else { - index += ies[index + 1] + 2; } - *out_index = index; -} - -void *wilc_parse_join_bss_param(struct cfg80211_bss *bss) -{ - struct join_bss_param *param; - u16 index = 0; - u8 rates_no = 0; - u8 pcipher_total_cnt = 0; - u8 auth_total_cnt = 0; - const u8 *tim_elm, *ssid_elm; - const struct cfg80211_bss_ies *ies = bss->ies; + rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, ies->data, ies->len); + if (rsn_ie) { + int offset = 8; - param = kzalloc(sizeof(*param), GFP_KERNEL); - if (!param) - return NULL; - - param->beacon_period = bss->beacon_interval; - param->cap_info = bss->capability; - ether_addr_copy(param->bssid, bss->bssid); - - ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len); - if (ssid_elm) { - param->ssid_len = ssid_elm[1]; - if (param->ssid_len <= IEEE80211_MAX_SSID_LEN) - memcpy(param->ssid, ssid_elm + 2, param->ssid_len); - else - param->ssid_len = 0; + param->mode_802_11i = 2; + param->rsn_found = true; + //extract RSN capabilities + offset += (rsn_ie[offset] * 4) + 2; + offset += (rsn_ie[offset] * 4) + 2; + memcpy(param->rsn_cap, &rsn_ie[offset], 2); } - tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len); - if (tim_elm && tim_elm[1] >= 2) - param->dtim_period = tim_elm[3]; + if (param->rsn_found) { + int i; - memset(param->rsn_pcip_policy, 0xFF, 3); - memset(param->rsn_auth_policy, 0xFF, 3); + param->rsn_grp_policy = crypto->cipher_group & 0xFF; + for (i = 0; i < crypto->n_ciphers_pairwise && i < 3; i++) + param->p_suites[i] = crypto->ciphers_pairwise[i] & 0xFF; - while (index < ies->len) - host_int_fill_join_bss_param(param, ies->data, &index, - &pcipher_total_cnt, - &auth_total_cnt, ies->tsf, - &rates_no); + for (i = 0; i < crypto->n_akm_suites && i < 3; i++) + param->akm_suites[i] = crypto->akm_suites[i] & 0xFF; + } return (void *)param; } diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 76da17267e24..659e8ccb653b 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -35,21 +35,6 @@ enum { #define WILC_MAX_ASSOC_RESP_FRAME_SIZE 256 -struct network_info { - s8 rssi; - u16 cap_info; - u8 ssid[MAX_SSID_LEN]; - u8 ssid_len; - u8 bssid[6]; - u16 beacon_period; - u8 dtim_period; - u8 ch; - u32 tsf_lo; - u8 *ies; - u16 ies_len; - u64 tsf; -}; - struct connect_info { u8 bssid[6]; u8 *req_ies; @@ -288,5 +273,6 @@ int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power); void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length); void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length); void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length); -void *wilc_parse_join_bss_param(struct cfg80211_bss *bss); +void *wilc_parse_join_bss_param(struct cfg80211_bss *bss, + struct cfg80211_crypto_settings *crypto); #endif diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 5da03bb88ab4..5070cad27738 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -422,7 +422,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, goto out_put_bss; } - join_params = wilc_parse_join_bss_param(bss); + join_params = wilc_parse_join_bss_param(bss, &sme->crypto); if (!join_params) { netdev_err(dev, "%s: failed to construct join param\n", __func__); diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index e2310d860291..961b6bb034a8 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -47,7 +47,6 @@ typedef void (*wilc_tx_complete_func_t)(void *, int); * ********************************************/ #define WILC_MULTICAST_TABLE_SIZE 8 -#define MAX_SSID_LEN 33 #define MAX_RATES_SUPPORTED 12 enum bss_types { -- cgit From f47e59eaab27eb251971b23a991d1bac6e088841 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 17 Jan 2019 13:21:30 +0000 Subject: staging: wilc1000: rename hidden_network related data structure Rename hidden_network related data structure to have more appropriate names, as it's used to keep search network SSID details. Signed-off-by: Ajay Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 40 +++++++++++------------ drivers/staging/wilc1000/host_interface.h | 11 ++++--- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 25 +++++++------- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 46fd448ddde7..6c2be4339ce2 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -234,7 +234,7 @@ static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt) 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_net) + struct wilc_probe_ssid *search) { int result = 0; struct wid wid_list[5]; @@ -242,7 +242,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u32 i; u8 *buffer; u8 valuesize = 0; - u8 *hdn_ntwk_wid_val = NULL; + u8 *search_ssid_vals = NULL; struct host_if_drv *hif_drv = vif->hif_drv; if (hif_drv->hif_state >= HOST_IF_SCANNING && @@ -260,26 +260,24 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, hif_drv->usr_scan_req.ch_cnt = 0; - if (hidden_net) { - wid_list[index].id = WID_SSID_PROBE_REQ; - wid_list[index].type = WID_STR; - - for (i = 0; i < hidden_net->n_ssids; i++) - valuesize += ((hidden_net->net_info[i].ssid_len) + 1); - hdn_ntwk_wid_val = kmalloc(valuesize + 1, GFP_KERNEL); - wid_list[index].val = hdn_ntwk_wid_val; - if (wid_list[index].val) { + if (search) { + for (i = 0; i < search->n_ssids; i++) + valuesize += ((search->ssid_info[i].ssid_len) + 1); + search_ssid_vals = kmalloc(valuesize + 1, GFP_KERNEL); + if (search_ssid_vals) { + wid_list[index].id = WID_SSID_PROBE_REQ; + wid_list[index].type = WID_STR; + wid_list[index].val = search_ssid_vals; buffer = wid_list[index].val; - *buffer++ = hidden_net->n_ssids; + *buffer++ = search->n_ssids; - for (i = 0; i < hidden_net->n_ssids; i++) { - *buffer++ = hidden_net->net_info[i].ssid_len; - memcpy(buffer, hidden_net->net_info[i].ssid, - hidden_net->net_info[i].ssid_len); - buffer += hidden_net->net_info[i].ssid_len; + for (i = 0; i < search->n_ssids; i++) { + *buffer++ = search->ssid_info[i].ssid_len; + memcpy(buffer, search->ssid_info[i].ssid, + search->ssid_info[i].ssid_len); + buffer += search->ssid_info[i].ssid_len; } - wid_list[index].size = (s32)(valuesize + 1); index++; } @@ -332,9 +330,9 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT)); error: - if (hidden_net) { - kfree(hidden_net->net_info); - kfree(hdn_ntwk_wid_val); + if (search) { + kfree(search->ssid_info); + kfree(search_ssid_vals); } return result; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 659e8ccb653b..e702404854f2 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -131,14 +131,15 @@ typedef void (*wilc_connect_result)(enum conn_event, typedef void (*wilc_remain_on_chan_expired)(void *, u32); typedef void (*wilc_remain_on_chan_ready)(void *); -struct hidden_net_info { - u8 *ssid; +struct wilc_probe_ssid_info { u8 ssid_len; + u8 *ssid; }; -struct hidden_network { - struct hidden_net_info *net_info; +struct wilc_probe_ssid { + struct wilc_probe_ssid_info *ssid_info; u8 n_ssids; + u32 size; }; struct user_scan_req { @@ -238,7 +239,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 *hidden_network); + struct wilc_probe_ssid *search); int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *cfg_param); int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 5070cad27738..1762c609962c 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -221,22 +221,23 @@ static int set_channel(struct wiphy *wiphy, static inline int wilc_wfi_cfg_alloc_fill_ssid(struct cfg80211_scan_request *request, - struct hidden_network *ntwk) + struct wilc_probe_ssid *search) { int i; int slot_id = 0; - ntwk->net_info = kcalloc(request->n_ssids, sizeof(*ntwk->net_info), - GFP_KERNEL); - if (!ntwk->net_info) + search->ssid_info = kcalloc(request->n_ssids, + sizeof(*search->ssid_info), GFP_KERNEL); + if (!search->ssid_info) goto out; - ntwk->n_ssids = request->n_ssids; + search->n_ssids = request->n_ssids; for (i = 0; i < request->n_ssids; i++) { if (request->ssids[i].ssid_len > 0) { - struct hidden_net_info *info = &ntwk->net_info[slot_id]; + struct wilc_probe_ssid_info *info; + info = &search->ssid_info[slot_id]; info->ssid = kmemdup(request->ssids[i].ssid, request->ssids[i].ssid_len, GFP_KERNEL); @@ -246,7 +247,7 @@ wilc_wfi_cfg_alloc_fill_ssid(struct cfg80211_scan_request *request, info->ssid_len = request->ssids[i].ssid_len; slot_id++; } else { - ntwk->n_ssids -= 1; + search->n_ssids -= 1; } } return 0; @@ -254,9 +255,9 @@ wilc_wfi_cfg_alloc_fill_ssid(struct cfg80211_scan_request *request, out_free: for (i = 0; i < slot_id; i++) - kfree(ntwk->net_info[i].ssid); + kfree(search->ssid_info[i].ssid); - kfree(ntwk->net_info); + kfree(search->ssid_info); out: return -ENOMEM; @@ -269,7 +270,7 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) u32 i; int ret = 0; u8 scan_ch_list[MAX_NUM_SCANNED_NETWORKS]; - struct hidden_network hidden_ntwk; + struct wilc_probe_ssid probe_ssid; priv->scan_req = request; @@ -283,7 +284,7 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) if (request->n_ssids >= 1) { if (wilc_wfi_cfg_alloc_fill_ssid(request, - &hidden_ntwk)) { + &probe_ssid)) { ret = -ENOMEM; goto out; } @@ -293,7 +294,7 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) request->n_channels, (const u8 *)request->ie, request->ie_len, cfg_scan_result, - (void *)priv, &hidden_ntwk); + (void *)priv, &probe_ssid); } else { ret = wilc_scan(vif, WILC_FW_USER_SCAN, WILC_FW_ACTIVE_SCAN, scan_ch_list, -- cgit From 734c3198d06e74777a15fc1e036e1c3d571858fa Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 17 Jan 2019 13:21:32 +0000 Subject: staging: wilc1000: use single struct for 'connect' related parameters Use single structure to store the connect request and response information. It helped in avoiding unnecessary buffer allocation to handle request and response flow. Signed-off-by: Ajay Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 217 ++++++---------------- drivers/staging/wilc1000/host_interface.h | 41 ++-- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 30 +-- 3 files changed, 84 insertions(+), 204 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 6c2be4339ce2..e37d8abcb9d3 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -344,8 +344,8 @@ static int wilc_send_connect_wid(struct wilc_vif *vif) struct wid wid_list[8]; u32 wid_cnt = 0, dummyval = 0; struct host_if_drv *hif_drv = vif->hif_drv; - struct user_conn_req *conn_attr = &hif_drv->usr_conn_req; - struct wilc_join_bss_param *bss_param = hif_drv->usr_conn_req.param; + struct wilc_conn_info *conn_attr = &hif_drv->conn_info; + struct wilc_join_bss_param *bss_param = conn_attr->param; wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT; wid_list[wid_cnt].type = WID_INT; @@ -367,8 +367,8 @@ static int wilc_send_connect_wid(struct wilc_vif *vif) wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE; wid_list[wid_cnt].type = WID_BIN_DATA; - wid_list[wid_cnt].val = conn_attr->ies; - wid_list[wid_cnt].size = conn_attr->ies_len; + wid_list[wid_cnt].val = conn_attr->req_ies; + wid_list[wid_cnt].size = conn_attr->req_ies_len; wid_cnt++; wid_list[wid_cnt].id = WID_11I_MODE; @@ -403,14 +403,8 @@ static int wilc_send_connect_wid(struct wilc_vif *vif) error: - kfree(conn_attr->bssid); - conn_attr->bssid = NULL; - - kfree(conn_attr->ssid); - conn_attr->ssid = NULL; - - kfree(conn_attr->ies); - conn_attr->ies = NULL; + kfree(conn_attr->req_ies); + conn_attr->req_ies = NULL; return result; } @@ -420,7 +414,6 @@ static void handle_connect_timeout(struct work_struct *work) struct host_if_msg *msg = container_of(work, struct host_if_msg, work); struct wilc_vif *vif = msg->vif; int result; - struct connect_info info; struct wid wid; u16 dummy_reason_code = 0; struct host_if_drv *hif_drv = vif->hif_drv; @@ -432,31 +425,11 @@ static void handle_connect_timeout(struct work_struct *work) hif_drv->hif_state = HOST_IF_IDLE; - memset(&info, 0, sizeof(struct connect_info)); - - if (hif_drv->usr_conn_req.conn_result) { - if (hif_drv->usr_conn_req.bssid) { - memcpy(info.bssid, - hif_drv->usr_conn_req.bssid, 6); - } - - if (hif_drv->usr_conn_req.ies) { - info.req_ies_len = hif_drv->usr_conn_req.ies_len; - info.req_ies = kmemdup(hif_drv->usr_conn_req.ies, - hif_drv->usr_conn_req.ies_len, - GFP_KERNEL); - if (!info.req_ies) - goto out; - } - - hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP, - &info, - WILC_MAC_STATUS_DISCONNECTED, - NULL, - hif_drv->usr_conn_req.arg); + if (hif_drv->conn_info.conn_result) { + hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_CONN_RESP, + WILC_MAC_STATUS_DISCONNECTED, + NULL, hif_drv->conn_info.arg); - kfree(info.req_ies); - info.req_ies = NULL; } else { netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); } @@ -471,14 +444,9 @@ static void handle_connect_timeout(struct work_struct *work) if (result) netdev_err(vif->ndev, "Failed to send disconnect\n"); - hif_drv->usr_conn_req.ssid_len = 0; - 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; - kfree(hif_drv->usr_conn_req.ies); - hif_drv->usr_conn_req.ies = NULL; + hif_drv->conn_info.req_ies_len = 0; + kfree(hif_drv->conn_info.req_ies); + hif_drv->conn_info.req_ies = NULL; out: kfree(msg); @@ -671,20 +639,8 @@ static void host_int_get_assoc_res_info(struct wilc_vif *vif, *rcvd_assoc_resp_info_len = wid.size; } -static inline void host_int_free_user_conn_req(struct host_if_drv *hif_drv) -{ - hif_drv->usr_conn_req.ssid_len = 0; - 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; - kfree(hif_drv->usr_conn_req.ies); - hif_drv->usr_conn_req.ies = NULL; -} - static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, - struct connect_info *ret_conn_info) + struct wilc_conn_info *ret_conn_info) { u8 *ies; u16 ies_len; @@ -708,10 +664,8 @@ static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, u8 mac_status) { - struct connect_info conn_info; struct host_if_drv *hif_drv = vif->hif_drv; - - memset(&conn_info, 0, sizeof(struct connect_info)); + struct wilc_conn_info *conn_info = &hif_drv->conn_info; if (mac_status == WILC_MAC_STATUS_CONNECTED) { u32 assoc_resp_info_len; @@ -727,7 +681,7 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, err = wilc_parse_assoc_resp_info(hif_drv->assoc_resp, assoc_resp_info_len, - &conn_info); + conn_info); if (err) netdev_err(vif->ndev, "wilc_parse_assoc_resp_info() returned error %d\n", @@ -735,31 +689,13 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, } } - if (hif_drv->usr_conn_req.bssid) { - memcpy(conn_info.bssid, hif_drv->usr_conn_req.bssid, 6); - - if (mac_status == WILC_MAC_STATUS_CONNECTED && - conn_info.status == WLAN_STATUS_SUCCESS) { - memcpy(hif_drv->assoc_bssid, - hif_drv->usr_conn_req.bssid, ETH_ALEN); - } - } - - if (hif_drv->usr_conn_req.ies) { - conn_info.req_ies = kmemdup(hif_drv->usr_conn_req.ies, - hif_drv->usr_conn_req.ies_len, - GFP_KERNEL); - if (conn_info.req_ies) - conn_info.req_ies_len = hif_drv->usr_conn_req.ies_len; - } - del_timer(&hif_drv->connect_timer); - hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP, - &conn_info, mac_status, NULL, - hif_drv->usr_conn_req.arg); + conn_info->conn_result(CONN_DISCONN_EVENT_CONN_RESP, mac_status, NULL, + hif_drv->conn_info.arg); if (mac_status == WILC_MAC_STATUS_CONNECTED && - conn_info.status == WLAN_STATUS_SUCCESS) { + conn_info->status == WLAN_STATUS_SUCCESS) { + ether_addr_copy(hif_drv->assoc_bssid, conn_info->bssid); wilc_set_power_mgmt(vif, 0, 0); hif_drv->hif_state = HOST_IF_CONNECTED; @@ -771,19 +707,19 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, hif_drv->hif_state = HOST_IF_IDLE; } - kfree(conn_info.resp_ies); - conn_info.resp_ies = NULL; + kfree(conn_info->resp_ies); + conn_info->resp_ies = NULL; + conn_info->resp_ies_len = 0; - kfree(conn_info.req_ies); - conn_info.req_ies = NULL; - host_int_free_user_conn_req(hif_drv); + kfree(conn_info->req_ies); + conn_info->req_ies = NULL; + conn_info->req_ies_len = 0; } static inline void host_int_handle_disconnect(struct wilc_vif *vif) { struct disconnect_info disconn_info; struct host_if_drv *hif_drv = vif->hif_drv; - wilc_connect_result conn_result = hif_drv->usr_conn_req.conn_result; memset(&disconn_info, 0, sizeof(struct disconnect_info)); @@ -796,19 +732,22 @@ static inline void host_int_handle_disconnect(struct wilc_vif *vif) disconn_info.ie = NULL; disconn_info.ie_len = 0; - if (conn_result) { + if (hif_drv->conn_info.conn_result) { vif->obtaining_ip = false; wilc_set_power_mgmt(vif, 0, 0); - conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL, 0, - &disconn_info, hif_drv->usr_conn_req.arg); + hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, + 0, &disconn_info, + hif_drv->conn_info.arg); } else { netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); } eth_zero_addr(hif_drv->assoc_bssid); - host_int_free_user_conn_req(hif_drv); + hif_drv->conn_info.req_ies_len = 0; + kfree(hif_drv->conn_info.req_ies); + hif_drv->conn_info.req_ies = NULL; hif_drv->hif_state = HOST_IF_IDLE; } @@ -834,7 +773,7 @@ static void handle_rcvd_gnrl_async_info(struct work_struct *work) if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP || hif_drv->hif_state == HOST_IF_CONNECTED || hif_drv->usr_scan_req.scan_result) { - if (!hif_drv->usr_conn_req.conn_result) { + if (!hif_drv->conn_info.conn_result) { netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); goto free_rcvd_info; @@ -875,7 +814,7 @@ int wilc_disconnect(struct wilc_vif *vif) struct host_if_drv *hif_drv = vif->hif_drv; struct disconnect_info disconn_info; struct user_scan_req *scan_req; - struct user_conn_req *conn_req; + struct wilc_conn_info *conn_info; int result; u16 dummy_reason_code = 0; @@ -900,7 +839,7 @@ int wilc_disconnect(struct wilc_vif *vif) disconn_info.ie = NULL; disconn_info.ie_len = 0; scan_req = &hif_drv->usr_scan_req; - conn_req = &hif_drv->usr_conn_req; + conn_info = &hif_drv->conn_info; if (scan_req->scan_result) { del_timer(&hif_drv->scan_timer); @@ -908,12 +847,12 @@ int wilc_disconnect(struct wilc_vif *vif) scan_req->scan_result = NULL; } - if (conn_req->conn_result) { + if (conn_info->conn_result) { if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) del_timer(&hif_drv->connect_timer); - conn_req->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL, - 0, &disconn_info, conn_req->arg); + conn_info->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, + 0, &disconn_info, conn_info->arg); } else { netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); } @@ -922,14 +861,9 @@ int wilc_disconnect(struct wilc_vif *vif) eth_zero_addr(hif_drv->assoc_bssid); - conn_req->ssid_len = 0; - kfree(conn_req->ssid); - conn_req->ssid = NULL; - kfree(conn_req->bssid); - conn_req->bssid = NULL; - conn_req->ies_len = 0; - kfree(conn_req->ies); - conn_req->ies = NULL; + conn_info->req_ies_len = 0; + kfree(conn_info->req_ies); + conn_info->req_ies = NULL; return 0; } @@ -1546,61 +1480,22 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) 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, - u8 security, enum authtype auth_type, - u8 channel, void *join_params) +int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies, + size_t ies_len) { int result; struct host_if_drv *hif_drv = vif->hif_drv; - struct user_conn_req *con_info = &hif_drv->usr_conn_req; + struct wilc_conn_info *conn_info = &hif_drv->conn_info; - if (!hif_drv || !connect_result) { - netdev_err(vif->ndev, - "%s: hif driver or connect result is NULL", - __func__); - return -EFAULT; - } - - if (!join_params) { - netdev_err(vif->ndev, "%s: joinparams is NULL\n", __func__); - return -EFAULT; - } - - if (hif_drv->usr_scan_req.scan_result) { - netdev_err(vif->ndev, "%s: Scan in progress\n", __func__); - return -EBUSY; - } - - con_info->security = security; - con_info->auth_type = auth_type; - con_info->ch = channel; - con_info->conn_result = connect_result; - con_info->arg = user_arg; - con_info->param = join_params; - - if (bssid) { - con_info->bssid = kmemdup(bssid, 6, GFP_KERNEL); - if (!con_info->bssid) - return -ENOMEM; - } - - if (ssid) { - con_info->ssid_len = ssid_len; - con_info->ssid = kmemdup(ssid, ssid_len, GFP_KERNEL); - if (!con_info->ssid) { - result = -ENOMEM; - goto free_bssid; - } - } + if (bssid) + ether_addr_copy(conn_info->bssid, bssid); if (ies) { - con_info->ies_len = ies_len; - con_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); - if (!con_info->ies) { + conn_info->req_ies_len = ies_len; + conn_info->req_ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!conn_info->req_ies) { result = -ENOMEM; - goto free_ssid; + return result; } } @@ -1615,13 +1510,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, return 0; free_ies: - kfree(con_info->ies); - -free_ssid: - kfree(con_info->ssid); - -free_bssid: - kfree(con_info->bssid); + kfree(conn_info->req_ies); return result; } @@ -1963,7 +1852,7 @@ void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length) return; } - if (!hif_drv->usr_conn_req.conn_result) { + if (!hif_drv->conn_info.conn_result) { netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); mutex_unlock(&hif_deinit_lock); return; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index e702404854f2..459a0847f7df 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -35,15 +35,6 @@ enum { #define WILC_MAX_ASSOC_RESP_FRAME_SIZE 256 -struct connect_info { - u8 bssid[6]; - u8 *req_ies; - size_t req_ies_len; - u8 *resp_ies; - u16 resp_ies_len; - u16 status; -}; - struct disconnect_info { u16 reason; u8 *ie; @@ -122,12 +113,6 @@ struct wilc_rcvd_net_info { typedef void (*wilc_scan_result)(enum scan_event, struct wilc_rcvd_net_info *, void *); -typedef void (*wilc_connect_result)(enum conn_event, - struct connect_info *, - u8, - struct disconnect_info *, - void *); - typedef void (*wilc_remain_on_chan_expired)(void *, u32); typedef void (*wilc_remain_on_chan_ready)(void *); @@ -148,17 +133,18 @@ struct user_scan_req { u32 ch_cnt; }; -struct user_conn_req { - u8 *bssid; - u8 *ssid; +struct wilc_conn_info { + u8 bssid[ETH_ALEN]; u8 security; enum authtype auth_type; - size_t ssid_len; - u8 *ies; - size_t ies_len; - wilc_connect_result conn_result; - bool ht_capable; u8 ch; + u8 *req_ies; + size_t req_ies_len; + u8 *resp_ies; + u16 resp_ies_len; + u16 status; + void (*conn_result)(enum conn_event evt, u8 status, + struct disconnect_info *info, void *priv_data); void *arg; void *param; }; @@ -175,7 +161,7 @@ struct remain_ch { struct wilc; struct host_if_drv { struct user_scan_req usr_scan_req; - struct user_conn_req usr_conn_req; + struct wilc_conn_info conn_info; struct remain_ch remain_on_ch; u8 remain_on_ch_pending; u64 p2p_timeout; @@ -228,11 +214,8 @@ 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 wilc_pmkid_attr *pmkid); int wilc_get_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 auth_type, - u8 channel, void *join_params); +int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies, + size_t ies_len); int wilc_disconnect(struct wilc_vif *vif); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 1762c609962c..bc1d7a70d14c 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -139,9 +139,7 @@ static void cfg_scan_result(enum scan_event scan_event, } } -static void cfg_connect_result(enum conn_event conn_disconn_evt, - struct connect_info *conn_info, - u8 mac_status, +static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status, struct disconnect_info *disconn_info, void *priv_data) { @@ -150,16 +148,15 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, struct wilc_vif *vif = netdev_priv(dev); struct wilc *wl = vif->wilc; struct host_if_drv *wfi_drv = priv->hif_drv; + struct wilc_conn_info *conn_info = &wfi_drv->conn_info; vif->connecting = false; if (conn_disconn_evt == CONN_DISCONN_EVENT_CONN_RESP) { - u16 connect_status; - - connect_status = conn_info->status; + u16 connect_status = conn_info->status; if (mac_status == WILC_MAC_STATUS_DISCONNECTED && - conn_info->status == WLAN_STATUS_SUCCESS) { + connect_status == WLAN_STATUS_SUCCESS) { connect_status = WLAN_STATUS_UNSPECIFIED_FAILURE; wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE); @@ -410,6 +407,12 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, auth_type = WILC_FW_AUTH_IEEE8021; } + if (wfi_drv->usr_scan_req.scan_result) { + netdev_err(vif->ndev, "%s: Scan in progress\n", __func__); + ret = -EBUSY; + goto out_error; + } + bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, sme->ssid, sme->ssid_len, IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY(sme->privacy)); @@ -438,16 +441,21 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, wilc_wlan_set_bssid(dev, bss->bssid, WILC_STATION_MODE); - ret = wilc_set_join_req(vif, bss->bssid, sme->ssid, - sme->ssid_len, sme->ie, sme->ie_len, - cfg_connect_result, (void *)priv, - security, auth_type, curr_channel, join_params); + wfi_drv->conn_info.security = security; + wfi_drv->conn_info.auth_type = auth_type; + wfi_drv->conn_info.ch = curr_channel; + wfi_drv->conn_info.conn_result = cfg_connect_result; + wfi_drv->conn_info.arg = priv; + wfi_drv->conn_info.param = join_params; + + ret = wilc_set_join_req(vif, bss->bssid, sme->ie, sme->ie_len); if (ret) { netdev_err(dev, "wilc_set_join_req(): Error\n"); ret = -ENOENT; if (!wfi_drv->p2p_connect) wlan_channel = INVALID_CHANNEL; wilc_wlan_set_bssid(dev, NULL, WILC_STATION_MODE); + wfi_drv->conn_info.conn_result = NULL; kfree(join_params); goto out_put_bss; } -- cgit From 94bb6d3353c21feb02c27eb1ee3feb2beaeecde4 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 17 Jan 2019 13:21:35 +0000 Subject: staging: wilc1000: refactor information message parsing logic Refactor code to avoid maintaining an unnecessary buffer to keep the information type message ('I' msg type). Signed-off-by: Ajay Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 66 ++++++++----------------------- 1 file changed, 16 insertions(+), 50 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index e37d8abcb9d3..a146b7810b2a 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -11,9 +11,8 @@ #define FALSE_FRMWR_CHANNEL 100 -struct rcvd_async_info { - u8 *buffer; - u32 len; +struct wilc_rcvd_mac_info { + u8 status; }; struct set_multicast { @@ -71,7 +70,7 @@ struct wilc_gtk_key { union message_body { struct wilc_rcvd_net_info net_info; - struct rcvd_async_info async_info; + struct wilc_rcvd_mac_info mac_info; struct set_multicast multicast_info; struct remain_ch remain_on_ch; char *data; @@ -755,55 +754,30 @@ static void handle_rcvd_gnrl_async_info(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); struct wilc_vif *vif = msg->vif; - struct rcvd_async_info *rcvd_info = &msg->body.async_info; - u8 msg_type; - u8 mac_status; + struct wilc_rcvd_mac_info *mac_info = &msg->body.mac_info; struct host_if_drv *hif_drv = vif->hif_drv; - if (!rcvd_info->buffer) { - netdev_err(vif->ndev, "%s: buffer is NULL\n", __func__); - goto free_msg; - } - if (!hif_drv) { netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__); - goto free_rcvd_info; + goto free_msg; } - if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP || - hif_drv->hif_state == HOST_IF_CONNECTED || - hif_drv->usr_scan_req.scan_result) { - if (!hif_drv->conn_info.conn_result) { - netdev_err(vif->ndev, "%s: conn_result is NULL\n", - __func__); - goto free_rcvd_info; - } - - msg_type = rcvd_info->buffer[0]; - - if ('I' != msg_type) { - netdev_err(vif->ndev, "Received Message incorrect.\n"); - goto free_rcvd_info; - } + if (!hif_drv->conn_info.conn_result) { + netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); + goto free_msg; + } - mac_status = rcvd_info->buffer[7]; - if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { - host_int_parse_assoc_resp_info(vif, mac_status); - } else if ((mac_status == WILC_MAC_STATUS_DISCONNECTED) && - (hif_drv->hif_state == HOST_IF_CONNECTED)) { + if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { + host_int_parse_assoc_resp_info(vif, mac_info->status); + } else if (mac_info->status == WILC_MAC_STATUS_DISCONNECTED) { + if (hif_drv->hif_state == HOST_IF_CONNECTED) { host_int_handle_disconnect(vif); - } else if ((mac_status == WILC_MAC_STATUS_DISCONNECTED) && - (hif_drv->usr_scan_req.scan_result)) { + } else if (hif_drv->usr_scan_req.scan_result) { del_timer(&hif_drv->scan_timer); - if (hif_drv->usr_scan_req.scan_result) - handle_scan_done(vif, SCAN_EVENT_ABORTED); + handle_scan_done(vif, SCAN_EVENT_ABORTED); } } -free_rcvd_info: - kfree(rcvd_info->buffer); - rcvd_info->buffer = NULL; - free_msg: kfree(msg); } @@ -1864,18 +1838,10 @@ void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length) return; } - msg->body.async_info.len = length; - msg->body.async_info.buffer = kmemdup(buffer, length, GFP_KERNEL); - if (!msg->body.async_info.buffer) { - kfree(msg); - mutex_unlock(&hif_deinit_lock); - return; - } - + msg->body.mac_info.status = buffer[7]; result = wilc_enqueue_work(msg); if (result) { netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg->body.async_info.buffer); kfree(msg); } -- cgit From 03cf31c41c2206731100aad51b98142b9e131fbb Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 17 Jan 2019 13:21:38 +0000 Subject: staging: wilc1000: remove 'disconnect_info' structure Remove 'disconnect_info' struct use because its passed values are not required in cfg_connect_result(). Signed-off-by: Ajay Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 24 +++++------------------ drivers/staging/wilc1000/host_interface.h | 9 +-------- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 12 ++++++------ 3 files changed, 12 insertions(+), 33 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a146b7810b2a..fa3af2c6bee6 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -427,7 +427,7 @@ static void handle_connect_timeout(struct work_struct *work) if (hif_drv->conn_info.conn_result) { hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_CONN_RESP, WILC_MAC_STATUS_DISCONNECTED, - NULL, hif_drv->conn_info.arg); + hif_drv->conn_info.arg); } else { netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); @@ -689,7 +689,7 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, } del_timer(&hif_drv->connect_timer); - conn_info->conn_result(CONN_DISCONN_EVENT_CONN_RESP, mac_status, NULL, + conn_info->conn_result(CONN_DISCONN_EVENT_CONN_RESP, mac_status, hif_drv->conn_info.arg); if (mac_status == WILC_MAC_STATUS_CONNECTED && @@ -717,27 +717,19 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, static inline void host_int_handle_disconnect(struct wilc_vif *vif) { - struct disconnect_info disconn_info; struct host_if_drv *hif_drv = vif->hif_drv; - memset(&disconn_info, 0, sizeof(struct disconnect_info)); - if (hif_drv->usr_scan_req.scan_result) { del_timer(&hif_drv->scan_timer); handle_scan_done(vif, SCAN_EVENT_ABORTED); } - disconn_info.reason = 0; - disconn_info.ie = NULL; - disconn_info.ie_len = 0; - if (hif_drv->conn_info.conn_result) { vif->obtaining_ip = false; wilc_set_power_mgmt(vif, 0, 0); hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, - 0, &disconn_info, - hif_drv->conn_info.arg); + 0, hif_drv->conn_info.arg); } else { netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); } @@ -786,7 +778,6 @@ int wilc_disconnect(struct wilc_vif *vif) { struct wid wid; struct host_if_drv *hif_drv = vif->hif_drv; - struct disconnect_info disconn_info; struct user_scan_req *scan_req; struct wilc_conn_info *conn_info; int result; @@ -807,11 +798,6 @@ int wilc_disconnect(struct wilc_vif *vif) return result; } - memset(&disconn_info, 0, sizeof(struct disconnect_info)); - - disconn_info.reason = 0; - disconn_info.ie = NULL; - disconn_info.ie_len = 0; scan_req = &hif_drv->usr_scan_req; conn_info = &hif_drv->conn_info; @@ -825,8 +811,8 @@ int wilc_disconnect(struct wilc_vif *vif) if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) del_timer(&hif_drv->connect_timer); - conn_info->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, - 0, &disconn_info, conn_info->arg); + conn_info->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0, + conn_info->arg); } else { netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); } diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 459a0847f7df..363db0b9fea8 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -35,12 +35,6 @@ enum { #define WILC_MAX_ASSOC_RESP_FRAME_SIZE 256 -struct disconnect_info { - u16 reason; - u8 *ie; - size_t ie_len; -}; - struct assoc_resp { __le16 capab_info; __le16 status_code; @@ -143,8 +137,7 @@ struct wilc_conn_info { u8 *resp_ies; u16 resp_ies_len; u16 status; - void (*conn_result)(enum conn_event evt, u8 status, - struct disconnect_info *info, void *priv_data); + void (*conn_result)(enum conn_event evt, u8 status, void *priv_data); void *arg; void *param; }; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index bc1d7a70d14c..79753ad15b7c 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -140,7 +140,6 @@ static void cfg_scan_result(enum scan_event scan_event, } static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status, - struct disconnect_info *disconn_info, void *priv_data) { struct wilc_priv *priv = priv_data; @@ -177,6 +176,8 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status, conn_info->resp_ies_len, connect_status, GFP_KERNEL); } else if (conn_disconn_evt == CONN_DISCONN_EVENT_DISCONN_NOTIF) { + u16 reason = 0; + vif->obtaining_ip = false; priv->p2p.local_random = 0x01; priv->p2p.recv_random = 0x00; @@ -186,14 +187,13 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status, if (!wfi_drv->p2p_connect) wlan_channel = INVALID_CHANNEL; + if (wfi_drv->ifc_up && dev == wl->vif[1]->ndev) - disconn_info->reason = 3; + reason = 3; else if (!wfi_drv->ifc_up && dev == wl->vif[1]->ndev) - disconn_info->reason = 1; + reason = 1; - cfg80211_disconnected(dev, disconn_info->reason, - disconn_info->ie, disconn_info->ie_len, - false, GFP_KERNEL); + cfg80211_disconnected(dev, reason, NULL, 0, false, GFP_KERNEL); } } -- cgit From a0c6a32e78a078fd5fa589ae2670155088e3a741 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 17 Jan 2019 13:21:41 +0000 Subject: staging: wilc1000: refactor handle_set_mcast_filter() Refactor handle_set_mcast_filter() by making use of put_unaligned32() to pack the data instead of byte operation. Signed-off-by: Ajay Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 37 +++++++++++++------------------ drivers/staging/wilc1000/host_interface.h | 2 +- drivers/staging/wilc1000/linux_wlan.c | 6 ++--- 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index fa3af2c6bee6..f4638654d1a5 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -15,8 +15,8 @@ struct wilc_rcvd_mac_info { u8 status; }; -struct set_multicast { - bool enabled; +struct wilc_set_multicast { + u32 enabled; u32 cnt; u8 *mc_list; }; @@ -71,7 +71,7 @@ struct wilc_gtk_key { union message_body { struct wilc_rcvd_net_info net_info; struct wilc_rcvd_mac_info mac_info; - struct set_multicast multicast_info; + struct wilc_set_multicast mc_info; struct remain_ch remain_on_ch; char *data; }; @@ -1067,32 +1067,27 @@ static void handle_set_mcast_filter(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); struct wilc_vif *vif = msg->vif; - struct set_multicast *hif_set_mc = &msg->body.multicast_info; + struct wilc_set_multicast *set_mc = &msg->body.mc_info; int result; struct wid wid; u8 *cur_byte; wid.id = WID_SETUP_MULTICAST_FILTER; wid.type = WID_BIN; - wid.size = sizeof(struct set_multicast) + (hif_set_mc->cnt * ETH_ALEN); + wid.size = sizeof(struct wilc_set_multicast) + (set_mc->cnt * ETH_ALEN); wid.val = kmalloc(wid.size, GFP_KERNEL); if (!wid.val) goto error; cur_byte = wid.val; - *cur_byte++ = (hif_set_mc->enabled & 0xFF); - *cur_byte++ = 0; - *cur_byte++ = 0; - *cur_byte++ = 0; + put_unaligned_le32(set_mc->enabled, cur_byte); + cur_byte += 4; - *cur_byte++ = (hif_set_mc->cnt & 0xFF); - *cur_byte++ = ((hif_set_mc->cnt >> 8) & 0xFF); - *cur_byte++ = ((hif_set_mc->cnt >> 16) & 0xFF); - *cur_byte++ = ((hif_set_mc->cnt >> 24) & 0xFF); + put_unaligned_le32(set_mc->cnt, cur_byte); + cur_byte += 4; - if (hif_set_mc->cnt > 0 && hif_set_mc->mc_list) - memcpy(cur_byte, hif_set_mc->mc_list, - ((hif_set_mc->cnt) * ETH_ALEN)); + if (set_mc->cnt > 0 && set_mc->mc_list) + memcpy(cur_byte, set_mc->mc_list, set_mc->cnt * ETH_ALEN); result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -1100,7 +1095,7 @@ static void handle_set_mcast_filter(struct work_struct *work) netdev_err(vif->ndev, "Failed to send setup multicast\n"); error: - kfree(hif_set_mc->mc_list); + kfree(set_mc->mc_list); kfree(wid.val); kfree(msg); } @@ -2150,7 +2145,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 enabled, u32 count, +int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count, u8 *mc_list) { int result; @@ -2160,9 +2155,9 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count, if (IS_ERR(msg)) return PTR_ERR(msg); - msg->body.multicast_info.enabled = enabled; - msg->body.multicast_info.cnt = count; - msg->body.multicast_info.mc_list = mc_list; + msg->body.mc_info.enabled = enabled; + msg->body.mc_info.cnt = count; + msg->body.mc_info.mc_list = mc_list; result = wilc_enqueue_work(msg); if (result) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 363db0b9fea8..527ae0523d67 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -230,7 +230,7 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); int wilc_edit_station(struct wilc_vif *vif, const u8 *mac, struct station_parameters *params); 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_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count, u8 *mc_list); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 5b554c6d39a1..87ec048824b8 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -811,12 +811,12 @@ static void wilc_set_multicast_list(struct net_device *dev) if (dev->flags & IFF_ALLMULTI || dev->mc.count > WILC_MULTICAST_TABLE_SIZE) { - wilc_setup_multicast_filter(vif, false, 0, NULL); + wilc_setup_multicast_filter(vif, 0, 0, NULL); return; } if (dev->mc.count == 0) { - wilc_setup_multicast_filter(vif, true, 0, NULL); + wilc_setup_multicast_filter(vif, 1, 0, NULL); return; } @@ -833,7 +833,7 @@ static void wilc_set_multicast_list(struct net_device *dev) cur_mc += ETH_ALEN; } - if (wilc_setup_multicast_filter(vif, true, dev->mc.count, mc_list)) + if (wilc_setup_multicast_filter(vif, 1, dev->mc.count, mc_list)) kfree(mc_list); } -- cgit From 65af887c3dfb87e244877dc28d0cceac8b60b6be Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 17 Jan 2019 13:21:44 +0000 Subject: staging: wilc1000: avoid the use of typedef for function pointers Remove typedef for function pointers. Signed-off-by: Ajay Singh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 13 +++++++------ drivers/staging/wilc1000/host_interface.h | 24 ++++++++++-------------- drivers/staging/wilc1000/wilc_wlan.c | 10 ++++++---- drivers/staging/wilc1000/wilc_wlan.h | 5 +++-- drivers/staging/wilc1000/wilc_wlan_if.h | 2 -- 5 files changed, 26 insertions(+), 28 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index f4638654d1a5..85573eb400af 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -231,9 +231,10 @@ static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt) } 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 wilc_probe_ssid *search) + u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t ies_len, + void (*scan_result_fn)(enum scan_event, + struct wilc_rcvd_net_info *, void *), + void *user_arg, struct wilc_probe_ssid *search) { int result = 0; struct wid wid_list[5]; @@ -322,7 +323,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, goto error; } - hif_drv->usr_scan_req.scan_result = scan_result; + hif_drv->usr_scan_req.scan_result = scan_result_fn; hif_drv->usr_scan_req.arg = user_arg; hif_drv->scan_timer_vif = vif; mod_timer(&hif_drv->scan_timer, @@ -1863,8 +1864,8 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length) 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 (*expired)(void *, u32), + void (*ready)(void *), void *user_arg) { struct remain_ch roc; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 527ae0523d67..7f3fc4c8cb8f 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -104,12 +104,6 @@ struct wilc_rcvd_net_info { struct ieee80211_mgmt *mgmt; }; -typedef void (*wilc_scan_result)(enum scan_event, struct wilc_rcvd_net_info *, - void *); - -typedef void (*wilc_remain_on_chan_expired)(void *, u32); -typedef void (*wilc_remain_on_chan_ready)(void *); - struct wilc_probe_ssid_info { u8 ssid_len; u8 *ssid; @@ -122,7 +116,8 @@ struct wilc_probe_ssid { }; struct user_scan_req { - wilc_scan_result scan_result; + void (*scan_result)(enum scan_event evt, + struct wilc_rcvd_net_info *info, void *priv); void *arg; u32 ch_cnt; }; @@ -145,8 +140,8 @@ struct wilc_conn_info { struct remain_ch { u16 ch; u32 duration; - wilc_remain_on_chan_expired expired; - wilc_remain_on_chan_ready ready; + void (*expired)(void *priv, u32 session_id); + void (*ready)(void *priv); void *arg; u32 id; }; @@ -213,9 +208,10 @@ int wilc_disconnect(struct wilc_vif *vif); 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 *user_arg, - struct wilc_probe_ssid *search); + u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t ies_len, + void (*scan_result_fn)(enum scan_event, + struct wilc_rcvd_net_info *, void *), + void *user_arg, struct wilc_probe_ssid *search); int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *cfg_param); int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); @@ -234,8 +230,8 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count, u8 *mc_list); 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 (*expired)(void *, u32), + void (*ready)(void *), void *user_arg); int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id); void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 16b6c5552432..9d3aaae2e74a 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -274,7 +274,8 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer, } int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, - u32 buffer_size, wilc_tx_complete_func_t func) + u32 buffer_size, + void (*tx_complete_fn)(void *, int)) { struct txq_entry_t *tqe; struct wilc_vif *vif = netdev_priv(dev); @@ -292,7 +293,7 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, tqe->type = WILC_NET_PKT; tqe->buffer = buffer; tqe->buffer_size = buffer_size; - tqe->tx_complete_func = func; + tqe->tx_complete_func = tx_complete_fn; tqe->priv = priv; tqe->ack_idx = NOT_TCP_ACK; @@ -303,7 +304,8 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, } int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, - u32 buffer_size, wilc_tx_complete_func_t func) + u32 buffer_size, + void (*tx_complete_fn)(void *, int)) { struct txq_entry_t *tqe; struct wilc_vif *vif = netdev_priv(dev); @@ -321,7 +323,7 @@ int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, tqe->type = WILC_MGMT_PKT; tqe->buffer = buffer; tqe->buffer_size = buffer_size; - tqe->tx_complete_func = func; + tqe->tx_complete_func = tx_complete_fn; tqe->priv = priv; tqe->ack_idx = NOT_TCP_ACK; wilc_wlan_txq_add_to_tail(dev, tqe); diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index c8ca13b34691..388045283dd5 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -275,7 +275,8 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, int wilc_wlan_start(struct wilc *wilc); int wilc_wlan_stop(struct wilc *wilc); int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, - u32 buffer_size, wilc_tx_complete_func_t func); + u32 buffer_size, + void (*tx_complete_fn)(void *, int)); 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); @@ -286,7 +287,7 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size); int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, - u32 buffer_size, wilc_tx_complete_func_t func); + u32 buffer_size, void (*func)(void *, int)); void wilc_chip_sleep_manually(struct wilc *wilc); void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value); diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index 961b6bb034a8..9370caaf2059 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -39,8 +39,6 @@ struct tx_complete_data { struct sk_buff *skb; }; -typedef void (*wilc_tx_complete_func_t)(void *, int); - /******************************************** * * Wlan Configuration ID -- cgit From 32462a98a0051b45c1d41e305e3803a5094da417 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 11 Jan 2019 12:05:10 -0600 Subject: staging: android: ion: Add proper header information The filenames in headers add nothing are often wrong after moves, lets drop them here and add a little description of the files contents. Signed-off-by: Andrew F. Davis Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 2 +- drivers/staging/android/ion/ion.h | 2 +- drivers/staging/android/ion/ion_carveout_heap.c | 2 +- drivers/staging/android/ion/ion_chunk_heap.c | 2 +- drivers/staging/android/ion/ion_cma_heap.c | 2 +- drivers/staging/android/ion/ion_heap.c | 2 +- drivers/staging/android/ion/ion_page_pool.c | 2 +- drivers/staging/android/ion/ion_system_heap.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index a0802de8c3a1..de1ca5e26a4a 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * drivers/staging/android/ion/ion.c + * ION Memory Allocator * * Copyright (C) 2011 Google, Inc. */ diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 47b594cf1ac9..ff455fdde1a8 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * drivers/staging/android/ion/ion.h + * ION Memory Allocator kernel interface header * * Copyright (C) 2011 Google, Inc. */ diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index e129237a0417..4a9f9c275654 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * drivers/staging/android/ion/ion_carveout_heap.c + * ION Memory Allocator carveout heap helper * * Copyright (C) 2011 Google, Inc. */ diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 159d72f5bc42..5a8917d9beac 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * drivers/staging/android/ion/ion_chunk_heap.c + * ION memory allocator chunk heap helper * * Copyright (C) 2012 Google, Inc. */ diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 3fafd013d80a..7b557dd5e78b 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * drivers/staging/android/ion/ion_cma_heap.c + * ION Memory Allocator CMA heap exporter * * Copyright (C) Linaro 2012 * Author: for ST-Ericsson. diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 31db510018a9..6ee0ac6e4be4 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * drivers/staging/android/ion/ion_heap.c + * ION Memory Allocator generic heap helpers * * Copyright (C) 2011 Google, Inc. */ diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index 0d2a95957ee8..fd4995fb676e 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * drivers/staging/android/ion/ion_mem_pool.c + * ION Memory Allocator page pool helpers * * Copyright (C) 2011 Google, Inc. */ diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 0383f7548d48..643b32099488 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * drivers/staging/android/ion/ion_system_heap.c + * ION Memory Allocator system heap exporter * * Copyright (C) 2011 Google, Inc. */ -- cgit From 2fbe1707bae2ba9f5f4f5dc96a26797ff3353b1f Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 11 Jan 2019 12:05:11 -0600 Subject: staging: android: ion: Remove empty ion_ioctl_dir() function This function is empty of real function and can be replaced with _IOC_DIR(). Signed-off-by: Andrew F. Davis Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion-ioctl.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c index a8d3cc412fb9..b366f97a5728 100644 --- a/drivers/staging/android/ion/ion-ioctl.c +++ b/drivers/staging/android/ion/ion-ioctl.c @@ -31,23 +31,11 @@ static int validate_ioctl_arg(unsigned int cmd, union ion_ioctl_arg *arg) return 0; } -/* fix up the cases where the ioctl direction bits are incorrect */ -static unsigned int ion_ioctl_dir(unsigned int cmd) -{ - switch (cmd) { - default: - return _IOC_DIR(cmd); - } -} - long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int ret = 0; - unsigned int dir; union ion_ioctl_arg data; - dir = ion_ioctl_dir(cmd); - if (_IOC_SIZE(cmd) > sizeof(data)) return -EINVAL; @@ -65,7 +53,7 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return ret; } - if (!(dir & _IOC_WRITE)) + if (!(_IOC_DIR(cmd) & _IOC_WRITE)) memset(&data, 0, sizeof(data)); switch (cmd) { @@ -90,7 +78,7 @@ long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -ENOTTY; } - if (dir & _IOC_READ) { + if (_IOC_DIR(cmd) & _IOC_READ) { if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) return -EFAULT; } -- cgit From 4514e79e5a6b2aa846b0b771270a8b655ef5001d Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 11 Jan 2019 12:05:12 -0600 Subject: staging: android: ion: Merge ion-ioctl.c into ion.c The file ion-ioctl.c is now much to small and tightly integrated with the main ion.c file to justify keeping it separate. Merge this file. Signed-off-by: Andrew F. Davis Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Makefile | 2 +- drivers/staging/android/ion/ion-ioctl.c | 86 --------------------------------- drivers/staging/android/ion/ion.c | 79 +++++++++++++++++++++++++++++- drivers/staging/android/ion/ion.h | 8 --- 4 files changed, 78 insertions(+), 97 deletions(-) delete mode 100644 drivers/staging/android/ion/ion-ioctl.c diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index bb30bf8774a0..17f3a7569e3d 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o +obj-$(CONFIG_ION) += ion.o ion_heap.o obj-$(CONFIG_ION_SYSTEM_HEAP) += ion_system_heap.o ion_page_pool.o obj-$(CONFIG_ION_CARVEOUT_HEAP) += ion_carveout_heap.o obj-$(CONFIG_ION_CHUNK_HEAP) += ion_chunk_heap.o diff --git a/drivers/staging/android/ion/ion-ioctl.c b/drivers/staging/android/ion/ion-ioctl.c deleted file mode 100644 index b366f97a5728..000000000000 --- a/drivers/staging/android/ion/ion-ioctl.c +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2011 Google, Inc. - */ - -#include -#include -#include -#include - -#include "ion.h" - -union ion_ioctl_arg { - struct ion_allocation_data allocation; - struct ion_heap_query query; -}; - -static int validate_ioctl_arg(unsigned int cmd, union ion_ioctl_arg *arg) -{ - switch (cmd) { - case ION_IOC_HEAP_QUERY: - if (arg->query.reserved0 || - arg->query.reserved1 || - arg->query.reserved2) - return -EINVAL; - break; - default: - break; - } - - return 0; -} - -long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - int ret = 0; - union ion_ioctl_arg data; - - if (_IOC_SIZE(cmd) > sizeof(data)) - return -EINVAL; - - /* - * The copy_from_user is unconditional here for both read and write - * to do the validate. If there is no write for the ioctl, the - * buffer is cleared - */ - if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) - return -EFAULT; - - ret = validate_ioctl_arg(cmd, &data); - if (ret) { - pr_warn_once("%s: ioctl validate failed\n", __func__); - return ret; - } - - if (!(_IOC_DIR(cmd) & _IOC_WRITE)) - memset(&data, 0, sizeof(data)); - - switch (cmd) { - case ION_IOC_ALLOC: - { - int fd; - - fd = ion_alloc(data.allocation.len, - data.allocation.heap_id_mask, - data.allocation.flags); - if (fd < 0) - return fd; - - data.allocation.fd = fd; - - break; - } - case ION_IOC_HEAP_QUERY: - ret = ion_query_heaps(&data.query); - break; - default: - return -ENOTTY; - } - - if (_IOC_DIR(cmd) & _IOC_READ) { - if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) - return -EFAULT; - } - return ret; -} diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index de1ca5e26a4a..2d6d8c0994b2 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -390,7 +390,7 @@ static const struct dma_buf_ops dma_buf_ops = { .unmap = ion_dma_buf_kunmap, }; -int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags) +static int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags) { struct ion_device *dev = internal_dev; struct ion_buffer *buffer = NULL; @@ -447,7 +447,7 @@ int ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags) return fd; } -int ion_query_heaps(struct ion_heap_query *query) +static int ion_query_heaps(struct ion_heap_query *query) { struct ion_device *dev = internal_dev; struct ion_heap_data __user *buffer = u64_to_user_ptr(query->heaps); @@ -492,6 +492,81 @@ out: return ret; } +union ion_ioctl_arg { + struct ion_allocation_data allocation; + struct ion_heap_query query; +}; + +static int validate_ioctl_arg(unsigned int cmd, union ion_ioctl_arg *arg) +{ + switch (cmd) { + case ION_IOC_HEAP_QUERY: + if (arg->query.reserved0 || + arg->query.reserved1 || + arg->query.reserved2) + return -EINVAL; + break; + default: + break; + } + + return 0; +} + +static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + union ion_ioctl_arg data; + + if (_IOC_SIZE(cmd) > sizeof(data)) + return -EINVAL; + + /* + * The copy_from_user is unconditional here for both read and write + * to do the validate. If there is no write for the ioctl, the + * buffer is cleared + */ + if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd))) + return -EFAULT; + + ret = validate_ioctl_arg(cmd, &data); + if (ret) { + pr_warn_once("%s: ioctl validate failed\n", __func__); + return ret; + } + + if (!(_IOC_DIR(cmd) & _IOC_WRITE)) + memset(&data, 0, sizeof(data)); + + switch (cmd) { + case ION_IOC_ALLOC: + { + int fd; + + fd = ion_alloc(data.allocation.len, + data.allocation.heap_id_mask, + data.allocation.flags); + if (fd < 0) + return fd; + + data.allocation.fd = fd; + + break; + } + case ION_IOC_HEAP_QUERY: + ret = ion_query_heaps(&data.query); + break; + default: + return -ENOTTY; + } + + if (_IOC_DIR(cmd) & _IOC_READ) { + if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd))) + return -EFAULT; + } + return ret; +} + static const struct file_operations ion_fops = { .owner = THIS_MODULE, .unlocked_ioctl = ion_ioctl, diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index ff455fdde1a8..084f246dcfc9 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -205,10 +205,6 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, int ion_heap_buffer_zero(struct ion_buffer *buffer); int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot); -int ion_alloc(size_t len, - unsigned int heap_id_mask, - unsigned int flags); - /** * ion_heap_init_shrinker * @heap: the heap @@ -330,8 +326,4 @@ void ion_page_pool_free(struct ion_page_pool *pool, struct page *page); int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, int nr_to_scan); -long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); - -int ion_query_heaps(struct ion_heap_query *query); - #endif /* _ION_H */ -- cgit From 6e42d12ce0dac1834767c2128444935b3a4f3322 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 11 Jan 2019 12:05:13 -0600 Subject: staging: android: ion: Remove leftover comment Since we use CMA APIs directly there is no device nor private heaps data, drop this comment. Fixes: 204f672255c2 ("staging: android: ion: Use CMA APIs directly") Signed-off-by: Andrew F. Davis Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_cma_heap.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 7b557dd5e78b..bf65e67ef9d8 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -111,10 +111,6 @@ static struct ion_heap *__ion_cma_heap_create(struct cma *cma) return ERR_PTR(-ENOMEM); cma_heap->heap.ops = &ion_cma_ops; - /* - * get device from private heaps data, later it will be - * used to make the link with reserved CMA memory - */ cma_heap->cma = cma; cma_heap->heap.type = ION_HEAP_TYPE_DMA; return &cma_heap->heap; -- cgit From c72f4e31c8a3c31bfdf4a1cbc595bb10d624c206 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 11 Jan 2019 12:05:14 -0600 Subject: staging: android: ion: Remove struct ion_platform_heap Now that ION heap registration has been re-worked to not depend on board files or have a central heap register helper there is no need to have this data structure. Most of the fields are unused. Some heap creation helpers are still available that use this to define the a heap but only use 2 or 3 elements from this struct, just convert these to get supplied these values from the heap registrar directly. Signed-off-by: Andrew F. Davis Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.h | 23 ----------------------- drivers/staging/android/ion/ion_carveout_heap.c | 12 ++++-------- drivers/staging/android/ion/ion_chunk_heap.c | 17 +++++++---------- 3 files changed, 11 insertions(+), 41 deletions(-) diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 084f246dcfc9..2ef78c951a6b 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -21,29 +21,6 @@ #include "../uapi/ion.h" -/** - * struct ion_platform_heap - defines a heap in the given platform - * @type: type of the heap from ion_heap_type enum - * @id: unique identifier for heap. When allocating higher numb ers - * will be allocated from first. At allocation these are passed - * as a bit mask and therefore can not exceed ION_NUM_HEAP_IDS. - * @name: used for debug purposes - * @base: base address of heap in physical memory if applicable - * @size: size of the heap in bytes if applicable - * @priv: private info passed from the board file - * - * Provided by the board file. - */ -struct ion_platform_heap { - enum ion_heap_type type; - unsigned int id; - const char *name; - phys_addr_t base; - size_t size; - phys_addr_t align; - void *priv; -}; - /** * struct ion_buffer - metadata for a particular buffer * @ref: reference count diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 4a9f9c275654..891f5703220b 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -103,17 +103,14 @@ static struct ion_heap_ops carveout_heap_ops = { .unmap_kernel = ion_heap_unmap_kernel, }; -struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) +struct ion_heap *ion_carveout_heap_create(phys_addr_t base, size_t size) { struct ion_carveout_heap *carveout_heap; int ret; struct page *page; - size_t size; - - page = pfn_to_page(PFN_DOWN(heap_data->base)); - size = heap_data->size; + page = pfn_to_page(PFN_DOWN(base)); ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL)); if (ret) return ERR_PTR(ret); @@ -127,9 +124,8 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) kfree(carveout_heap); return ERR_PTR(-ENOMEM); } - carveout_heap->base = heap_data->base; - gen_pool_add(carveout_heap->pool, carveout_heap->base, heap_data->size, - -1); + carveout_heap->base = base; + gen_pool_add(carveout_heap->pool, carveout_heap->base, size, -1); carveout_heap->heap.ops = &carveout_heap_ops; carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT; carveout_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 5a8917d9beac..c2321a047f0f 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -108,16 +108,13 @@ static struct ion_heap_ops chunk_heap_ops = { .unmap_kernel = ion_heap_unmap_kernel, }; -struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) +struct ion_heap *ion_chunk_heap_create(phys_addr_t base, size_t size, size_t chunk_size) { struct ion_chunk_heap *chunk_heap; int ret; struct page *page; - size_t size; - - page = pfn_to_page(PFN_DOWN(heap_data->base)); - size = heap_data->size; + page = pfn_to_page(PFN_DOWN(base)); ret = ion_heap_pages_zero(page, size, pgprot_writecombine(PAGE_KERNEL)); if (ret) return ERR_PTR(ret); @@ -126,23 +123,23 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) if (!chunk_heap) return ERR_PTR(-ENOMEM); - chunk_heap->chunk_size = (unsigned long)heap_data->priv; + chunk_heap->chunk_size = chunk_size; chunk_heap->pool = gen_pool_create(get_order(chunk_heap->chunk_size) + PAGE_SHIFT, -1); if (!chunk_heap->pool) { ret = -ENOMEM; goto error_gen_pool_create; } - chunk_heap->base = heap_data->base; - chunk_heap->size = heap_data->size; + chunk_heap->base = base; + chunk_heap->size = size; chunk_heap->allocated = 0; - gen_pool_add(chunk_heap->pool, chunk_heap->base, heap_data->size, -1); + gen_pool_add(chunk_heap->pool, chunk_heap->base, size, -1); chunk_heap->heap.ops = &chunk_heap_ops; chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; pr_debug("%s: base %pa size %zu\n", __func__, - &chunk_heap->base, heap_data->size); + &chunk_heap->base, size); return &chunk_heap->heap; -- cgit From 4d5119f448a879692c5fc4b5e9ad7d7b71170fb5 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 11 Jan 2019 12:05:15 -0600 Subject: staging: android: ion: Fixup some white-space issues Add white-space for easier reading and remove some where it does not belong. No functional changes, they just bug me.. Signed-off-by: Andrew F. Davis Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_carveout_heap.c | 1 + drivers/staging/android/ion/ion_chunk_heap.c | 2 +- drivers/staging/android/ion/ion_heap.c | 6 ++++++ drivers/staging/android/ion/ion_system_heap.c | 6 +++++- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 891f5703220b..be80671df9c8 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -44,6 +44,7 @@ static void ion_carveout_free(struct ion_heap *heap, phys_addr_t addr, if (addr == ION_CARVEOUT_ALLOCATE_FAIL) return; + gen_pool_free(carveout_heap->pool, addr, size); } diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index c2321a047f0f..b82eac1c2d7a 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -4,6 +4,7 @@ * * Copyright (C) 2012 Google, Inc. */ + #include #include #include @@ -147,4 +148,3 @@ error_gen_pool_create: kfree(chunk_heap); return ERR_PTR(ret); } - diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 6ee0ac6e4be4..473b465724f1 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -14,6 +14,7 @@ #include #include #include + #include "ion.h" void *ion_heap_map_kernel(struct ion_heap *heap, @@ -92,6 +93,7 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, if (addr >= vma->vm_end) return 0; } + return 0; } @@ -254,6 +256,7 @@ int ion_heap_init_deferred_free(struct ion_heap *heap) return PTR_ERR_OR_ZERO(heap->task); } sched_setscheduler(heap->task, SCHED_IDLE, ¶m); + return 0; } @@ -265,8 +268,10 @@ static unsigned long ion_heap_shrink_count(struct shrinker *shrinker, int total = 0; total = ion_heap_freelist_size(heap) / PAGE_SIZE; + if (heap->ops->shrink) total += heap->ops->shrink(heap, sc->gfp_mask, 0); + return total; } @@ -295,6 +300,7 @@ static unsigned long ion_heap_shrink_scan(struct shrinker *shrinker, if (heap->ops->shrink) freed += heap->ops->shrink(heap, sc->gfp_mask, to_scan); + return freed; } diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 643b32099488..ec526a464db8 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -13,6 +13,7 @@ #include #include #include + #include "ion.h" #define NUM_ORDERS ARRAY_SIZE(orders) @@ -236,6 +237,7 @@ static int ion_system_heap_create_pools(struct ion_page_pool **pools) goto err_create_pool; pools[i] = pool; } + return 0; err_create_pool: @@ -274,6 +276,7 @@ static int ion_system_heap_create(void) heap->name = "ion_system_heap"; ion_device_add_heap(heap); + return 0; } device_initcall(ion_system_heap_create); @@ -355,6 +358,7 @@ static struct ion_heap *__ion_system_contig_heap_create(void) heap->ops = &kmalloc_ops; heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG; heap->name = "ion_system_contig_heap"; + return heap; } @@ -367,7 +371,7 @@ static int ion_system_contig_heap_create(void) return PTR_ERR(heap); ion_device_add_heap(heap); + return 0; } device_initcall(ion_system_contig_heap_create); - -- cgit From 96d12a0d94097ba5797230b76c9bdc5c798750f3 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 11 Jan 2019 12:05:16 -0600 Subject: staging: android: ion: Sync comment docs with struct ion_buffer This struct is no longer documented correctly, fix this. Signed-off-by: Andrew F. Davis Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index 2ef78c951a6b..e291299fd35f 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -23,8 +23,8 @@ /** * struct ion_buffer - metadata for a particular buffer - * @ref: reference count * @node: node in the ion_device buffers tree + * @list: element in list of deferred freeable buffers * @dev: back pointer to the ion_device * @heap: back pointer to the heap the buffer came from * @flags: buffer specific flags @@ -35,7 +35,8 @@ * @lock: protects the buffers cnt fields * @kmap_cnt: number of times the buffer is mapped to the kernel * @vaddr: the kernel mapping if kmap_cnt is not zero - * @sg_table: the sg table for the buffer if dmap_cnt is not zero + * @sg_table: the sg table for the buffer + * @attachments: list of devices attached to this buffer */ struct ion_buffer { union { @@ -151,12 +152,16 @@ struct ion_heap { unsigned long flags; unsigned int id; const char *name; + + /* deferred free support */ struct shrinker shrinker; struct list_head free_list; size_t free_list_size; spinlock_t free_lock; wait_queue_head_t waitqueue; struct task_struct *task; + + /* heap statistics */ u64 num_of_buffers; u64 num_of_alloc_bytes; u64 alloc_bytes_wm; -- cgit From 298783c27e291be5b38ad460eb909b46d353f9cd Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 11 Jan 2019 12:05:17 -0600 Subject: staging: android: ion: Remove base from ion_carveout_heap The base address is not used anywhere and tracked by the pool allocator. No need to store this anymore. Signed-off-by: Andrew F. Davis Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_carveout_heap.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index be80671df9c8..ab9b72adca9c 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -20,7 +20,6 @@ struct ion_carveout_heap { struct ion_heap heap; struct gen_pool *pool; - phys_addr_t base; }; static phys_addr_t ion_carveout_allocate(struct ion_heap *heap, @@ -125,8 +124,7 @@ struct ion_heap *ion_carveout_heap_create(phys_addr_t base, size_t size) kfree(carveout_heap); return ERR_PTR(-ENOMEM); } - carveout_heap->base = base; - gen_pool_add(carveout_heap->pool, carveout_heap->base, size, -1); + gen_pool_add(carveout_heap->pool, base, size, -1); carveout_heap->heap.ops = &carveout_heap_ops; carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT; carveout_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; -- cgit From dad407ae7df9448762e2e04b22fecf5ba5ce4e2d Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 11 Jan 2019 12:05:18 -0600 Subject: staging: android: ion: Remove base from ion_chunk_heap The base address is not used anywhere and tracked by the pool allocator. No need to store this anymore. Signed-off-by: Andrew F. Davis Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_chunk_heap.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index b82eac1c2d7a..899380beeee1 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -18,7 +18,6 @@ struct ion_chunk_heap { struct ion_heap heap; struct gen_pool *pool; - phys_addr_t base; unsigned long chunk_size; unsigned long size; unsigned long allocated; @@ -131,16 +130,14 @@ struct ion_heap *ion_chunk_heap_create(phys_addr_t base, size_t size, size_t chu ret = -ENOMEM; goto error_gen_pool_create; } - chunk_heap->base = base; chunk_heap->size = size; chunk_heap->allocated = 0; - gen_pool_add(chunk_heap->pool, chunk_heap->base, size, -1); + gen_pool_add(chunk_heap->pool, base, size, -1); chunk_heap->heap.ops = &chunk_heap_ops; chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; - pr_debug("%s: base %pa size %zu\n", __func__, - &chunk_heap->base, size); + pr_debug("%s: base %pa size %zu\n", __func__, &base, size); return &chunk_heap->heap; -- cgit From 032ecb59aa3878d6d9984068d715ab9ce7e2e503 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 11 Jan 2019 12:05:19 -0600 Subject: staging: android: ion: Remove unused headers Various cleanups have removed the use of some headers in ION, remove these here. Signed-off-by: Andrew F. Davis Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 3 --- drivers/staging/android/ion/ion_carveout_heap.c | 4 ++-- drivers/staging/android/ion/ion_chunk_heap.c | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 2d6d8c0994b2..bba5f682bc25 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -5,7 +5,6 @@ * Copyright (C) 2011 Google, Inc. */ -#include #include #include #include @@ -14,10 +13,8 @@ #include #include #include -#include #include #include -#include #include #include #include diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index ab9b72adca9c..bb9d614767a2 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -4,7 +4,7 @@ * * Copyright (C) 2011 Google, Inc. */ -#include + #include #include #include @@ -12,7 +12,7 @@ #include #include #include -#include + #include "ion.h" #define ION_CARVEOUT_ALLOCATE_FAIL -1 diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c index 899380beeee1..3cdde9c1a717 100644 --- a/drivers/staging/android/ion/ion_chunk_heap.c +++ b/drivers/staging/android/ion/ion_chunk_heap.c @@ -8,11 +8,10 @@ #include #include #include -#include #include #include #include -#include + #include "ion.h" struct ion_chunk_heap { -- cgit From c440eee1a7a1d0f2d5fc2ee6049e4a05da540f01 Mon Sep 17 00:00:00 2001 From: Nishad Kamdar Date: Wed, 16 Jan 2019 23:00:50 +0530 Subject: Staging: fbtft: Switch to the gpio descriptor interface This switches the fbtft driver to use GPIO descriptors rather than numerical gpios: Utilize the GPIO library's intrinsic handling of OF GPIOs and polarity. If the line is flagged active low, gpiolib will deal with this. Remove gpios from platform device structure. Neither assign statically numbers to gpios in platform device nor allow gpios to be parsed as module parameters. Signed-off-by: Nishad Kamdar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_agm1264k-fl.c | 52 ++--- drivers/staging/fbtft/fb_bd663474.c | 6 +- drivers/staging/fbtft/fb_ili9163.c | 6 +- drivers/staging/fbtft/fb_ili9320.c | 2 +- drivers/staging/fbtft/fb_ili9325.c | 6 +- drivers/staging/fbtft/fb_ili9340.c | 2 +- drivers/staging/fbtft/fb_pcd8544.c | 4 +- drivers/staging/fbtft/fb_ra8875.c | 4 +- drivers/staging/fbtft/fb_s6d1121.c | 6 +- drivers/staging/fbtft/fb_sh1106.c | 2 +- drivers/staging/fbtft/fb_ssd1289.c | 6 +- drivers/staging/fbtft/fb_ssd1305.c | 4 +- drivers/staging/fbtft/fb_ssd1306.c | 4 +- drivers/staging/fbtft/fb_ssd1325.c | 6 +- drivers/staging/fbtft/fb_ssd1331.c | 10 +- drivers/staging/fbtft/fb_ssd1351.c | 2 +- drivers/staging/fbtft/fb_tls8204.c | 6 +- drivers/staging/fbtft/fb_uc1611.c | 4 +- drivers/staging/fbtft/fb_uc1701.c | 6 +- drivers/staging/fbtft/fb_upd161704.c | 6 +- drivers/staging/fbtft/fb_watterott.c | 4 +- drivers/staging/fbtft/fbtft-bus.c | 6 +- drivers/staging/fbtft/fbtft-core.c | 173 +++-------------- drivers/staging/fbtft/fbtft-io.c | 26 +-- drivers/staging/fbtft/fbtft.h | 21 +- drivers/staging/fbtft/fbtft_device.c | 344 +-------------------------------- drivers/staging/fbtft/flexfb.c | 12 +- 27 files changed, 143 insertions(+), 587 deletions(-) diff --git a/drivers/staging/fbtft/fb_agm1264k-fl.c b/drivers/staging/fbtft/fb_agm1264k-fl.c index f6f30f5bf15a..8f27bd8da17d 100644 --- a/drivers/staging/fbtft/fb_agm1264k-fl.c +++ b/drivers/staging/fbtft/fb_agm1264k-fl.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include @@ -79,14 +79,14 @@ static int init_display(struct fbtft_par *par) static void reset(struct fbtft_par *par) { - if (par->gpio.reset == -1) + if (!par->gpio.reset) return; dev_dbg(par->info->device, "%s()\n", __func__); - gpio_set_value(par->gpio.reset, 0); + gpiod_set_value(par->gpio.reset, 0); udelay(20); - gpio_set_value(par->gpio.reset, 1); + gpiod_set_value(par->gpio.reset, 1); mdelay(120); } @@ -98,30 +98,30 @@ static int verify_gpios(struct fbtft_par *par) dev_dbg(par->info->device, "%s()\n", __func__); - if (par->EPIN < 0) { + if (!par->EPIN) { dev_err(par->info->device, "Missing info about 'wr' (aka E) gpio. Aborting.\n"); return -EINVAL; } for (i = 0; i < 8; ++i) { - if (par->gpio.db[i] < 0) { + if (!par->gpio.db[i]) { dev_err(par->info->device, "Missing info about 'db[%i]' gpio. Aborting.\n", i); return -EINVAL; } } - if (par->CS0 < 0) { + if (!par->CS0) { dev_err(par->info->device, "Missing info about 'cs0' gpio. Aborting.\n"); return -EINVAL; } - if (par->CS1 < 0) { + if (!par->CS1) { dev_err(par->info->device, "Missing info about 'cs1' gpio. Aborting.\n"); return -EINVAL; } - if (par->RW < 0) { + if (!par->RW) { dev_err(par->info->device, "Missing info about 'rw' gpio. Aborting.\n"); return -EINVAL; @@ -139,22 +139,22 @@ request_gpios_match(struct fbtft_par *par, const struct fbtft_gpio *gpio) if (strcasecmp(gpio->name, "wr") == 0) { /* left ks0108 E pin */ par->EPIN = gpio->gpio; - return GPIOF_OUT_INIT_LOW; + return GPIOD_OUT_LOW; } else if (strcasecmp(gpio->name, "cs0") == 0) { /* left ks0108 controller pin */ par->CS0 = gpio->gpio; - return GPIOF_OUT_INIT_HIGH; + return GPIOD_OUT_HIGH; } else if (strcasecmp(gpio->name, "cs1") == 0) { /* right ks0108 controller pin */ par->CS1 = gpio->gpio; - return GPIOF_OUT_INIT_HIGH; + return GPIOD_OUT_HIGH; } /* if write (rw = 0) e(1->0) perform write */ /* if read (rw = 1) e(0->1) set data on D0-7*/ else if (strcasecmp(gpio->name, "rw") == 0) { par->RW = gpio->gpio; - return GPIOF_OUT_INIT_LOW; + return GPIOD_OUT_LOW; } return FBTFT_GPIO_NO_MATCH; @@ -194,15 +194,15 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) /* select chip */ if (*buf) { /* cs1 */ - gpio_set_value(par->CS0, 1); - gpio_set_value(par->CS1, 0); + gpiod_set_value(par->CS0, 1); + gpiod_set_value(par->CS1, 0); } else { /* cs0 */ - gpio_set_value(par->CS0, 0); - gpio_set_value(par->CS1, 1); + gpiod_set_value(par->CS0, 0); + gpiod_set_value(par->CS1, 1); } - gpio_set_value(par->RS, 0); /* RS->0 (command mode) */ + gpiod_set_value(par->RS, 0); /* RS->0 (command mode) */ len--; if (len) { @@ -364,7 +364,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) write_reg(par, 0x00, (0x17 << 3) | (u8)y); /* write bitmap */ - gpio_set_value(par->RS, 1); /* RS->1 (data mode) */ + gpiod_set_value(par->RS, 1); /* RS->1 (data mode) */ ret = par->fbtftops.write(par, buf, len); if (ret < 0) dev_err(par->info->device, @@ -387,7 +387,7 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) write_reg(par, 0x01, (0x17 << 3) | (u8)y); /* write bitmap */ - gpio_set_value(par->RS, 1); /* RS->1 (data mode) */ + gpiod_set_value(par->RS, 1); /* RS->1 (data mode) */ par->fbtftops.write(par, buf, len); if (ret < 0) dev_err(par->info->device, @@ -397,8 +397,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) } kfree(convert_buf); - gpio_set_value(par->CS0, 1); - gpio_set_value(par->CS1, 1); + gpiod_set_value(par->CS0, 1); + gpiod_set_value(par->CS1, 1); return ret; } @@ -408,7 +408,7 @@ static int write(struct fbtft_par *par, void *buf, size_t len) fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, "%s(len=%d): ", __func__, len); - gpio_set_value(par->RW, 0); /* set write mode */ + gpiod_set_value(par->RW, 0); /* set write mode */ while (len--) { u8 i, data; @@ -417,12 +417,12 @@ static int write(struct fbtft_par *par, void *buf, size_t len) /* set data bus */ for (i = 0; i < 8; ++i) - gpio_set_value(par->gpio.db[i], data & (1 << i)); + gpiod_set_value(par->gpio.db[i], data & (1 << i)); /* set E */ - gpio_set_value(par->EPIN, 1); + gpiod_set_value(par->EPIN, 1); udelay(5); /* unset E - write */ - gpio_set_value(par->EPIN, 0); + gpiod_set_value(par->EPIN, 0); udelay(1); } diff --git a/drivers/staging/fbtft/fb_bd663474.c b/drivers/staging/fbtft/fb_bd663474.c index a58c514f4721..b6c6d66e4eb1 100644 --- a/drivers/staging/fbtft/fb_bd663474.c +++ b/drivers/staging/fbtft/fb_bd663474.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include "fbtft.h" @@ -24,8 +24,8 @@ static int init_display(struct fbtft_par *par) { - if (par->gpio.cs != -1) - gpio_set_value(par->gpio.cs, 0); /* Activate chip */ + if (!par->gpio.cs) + gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ par->fbtftops.reset(par); diff --git a/drivers/staging/fbtft/fb_ili9163.c b/drivers/staging/fbtft/fb_ili9163.c index 86e140244aab..d609a2b67db9 100644 --- a/drivers/staging/fbtft/fb_ili9163.c +++ b/drivers/staging/fbtft/fb_ili9163.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include