From f339f979bb333ed51ff2d700ccd01bc20e9a9b98 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 13 Nov 2019 11:24:53 +0200 Subject: [PATCH 001/353] iio: buffer-dmaengine: Use dma_request_chan() directly for channel request dma_request_slave_channel_reason() is: dma_request_chan(dev, name) Signed-off-by: Peter Ujfalusi Reviewed-by: Vinod Koul Signed-off-by: Jonathan Cameron --- drivers/iio/buffer/industrialio-buffer-dmaengine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index bea4a75e92f1..b7b5a934e9b2 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -150,7 +150,7 @@ struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, if (!dmaengine_buffer) return ERR_PTR(-ENOMEM); - chan = dma_request_slave_channel_reason(dev, channel); + chan = dma_request_chan(dev, channel); if (IS_ERR(chan)) { ret = PTR_ERR(chan); goto err_free; From ca69300173b642ba64118200172171ea5967b6c5 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Fri, 15 Nov 2019 15:57:20 +0200 Subject: [PATCH 002/353] iio: adc: Add support for AD7091R5 ADC AD7091R5 is 4-Channel, I2C, Ultra Low Power,12-Bit ADC. This driver will also support AD7091R2/4/8 in the future. Datasheet: Link: https://www.analog.com/media/en/technical-documentation/data-sheets/ad7091r-5.pdf Signed-off-by: Paul Cercueil Co-developed-by: Beniamin Bia Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 7 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ad7091r-base.c | 260 +++++++++++++++++++++++++++++++++ drivers/iio/adc/ad7091r-base.h | 25 ++++ drivers/iio/adc/ad7091r5.c | 108 ++++++++++++++ 5 files changed, 401 insertions(+) create mode 100644 drivers/iio/adc/ad7091r-base.c create mode 100644 drivers/iio/adc/ad7091r-base.h create mode 100644 drivers/iio/adc/ad7091r5.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 5d8540b7b427..976567d4dbef 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -32,6 +32,13 @@ config AD7124 To compile this driver as a module, choose M here: the module will be called ad7124. +config AD7091R5 + tristate "Analog Devices AD7091R5 ADC Driver" + depends on I2C + select REGMAP_I2C + help + Say yes here to build support for Analog Devices AD7091R-5 ADC. + config AD7266 tristate "Analog Devices AD7265/AD7266 ADC driver" depends on SPI_MASTER diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index a1f1fbec0f87..84936ec24411 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o obj-$(CONFIG_AD7124) += ad7124.o +obj-$(CONFIG_AD7091R5) += ad7091r5.o ad7091r-base.o obj-$(CONFIG_AD7266) += ad7266.o obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7292) += ad7292.o diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c new file mode 100644 index 000000000000..854de7c654c2 --- /dev/null +++ b/drivers/iio/adc/ad7091r-base.c @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AD7091RX Analog to Digital converter driver + * + * Copyright 2014-2019 Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include + +#include "ad7091r-base.h" + +#define AD7091R_REG_RESULT 0 +#define AD7091R_REG_CHANNEL 1 +#define AD7091R_REG_CONF 2 +#define AD7091R_REG_ALERT 3 +#define AD7091R_REG_CH_LOW_LIMIT(ch) ((ch) * 3 + 4) +#define AD7091R_REG_CH_HIGH_LIMIT(ch) ((ch) * 3 + 5) +#define AD7091R_REG_CH_HYSTERESIS(ch) ((ch) * 3 + 6) + +/* AD7091R_REG_RESULT */ +#define AD7091R_REG_RESULT_CH_ID(x) (((x) >> 13) & 0x3) +#define AD7091R_REG_RESULT_CONV_RESULT(x) ((x) & 0xfff) + +/* AD7091R_REG_CONF */ +#define AD7091R_REG_CONF_AUTO BIT(8) +#define AD7091R_REG_CONF_CMD BIT(10) + +#define AD7091R_REG_CONF_MODE_MASK \ + (AD7091R_REG_CONF_AUTO | AD7091R_REG_CONF_CMD) + +enum ad7091r_mode { + AD7091R_MODE_SAMPLE, + AD7091R_MODE_COMMAND, + AD7091R_MODE_AUTOCYCLE, +}; + +struct ad7091r_state { + struct device *dev; + struct regmap *map; + const struct ad7091r_chip_info *chip_info; + enum ad7091r_mode mode; + struct mutex lock; /*lock to prevent concurent reads */ +}; + +static int ad7091r_set_mode(struct ad7091r_state *st, enum ad7091r_mode mode) +{ + int ret, conf; + + switch (mode) { + case AD7091R_MODE_SAMPLE: + conf = 0; + break; + case AD7091R_MODE_COMMAND: + conf = AD7091R_REG_CONF_CMD; + break; + case AD7091R_MODE_AUTOCYCLE: + conf = AD7091R_REG_CONF_AUTO; + break; + default: + return -EINVAL; + } + + ret = regmap_update_bits(st->map, AD7091R_REG_CONF, + AD7091R_REG_CONF_MODE_MASK, conf); + if (ret) + return ret; + + st->mode = mode; + + return 0; +} + +static int ad7091r_set_channel(struct ad7091r_state *st, unsigned int channel) +{ + unsigned int dummy; + int ret; + + /* AD7091R_REG_CHANNEL specified which channels to be converted */ + ret = regmap_write(st->map, AD7091R_REG_CHANNEL, + BIT(channel) | (BIT(channel) << 8)); + if (ret) + return ret; + + /* + * There is a latency of one conversion before the channel conversion + * sequence is updated + */ + return regmap_read(st->map, AD7091R_REG_RESULT, &dummy); +} + +static int ad7091r_read_one(struct iio_dev *iio_dev, + unsigned int channel, unsigned int *read_val) +{ + struct ad7091r_state *st = iio_priv(iio_dev); + unsigned int val; + int ret; + + ret = ad7091r_set_channel(st, channel); + if (ret) + return ret; + + ret = regmap_read(st->map, AD7091R_REG_RESULT, &val); + if (ret) + return ret; + + if (AD7091R_REG_RESULT_CH_ID(val) != channel) + return -EIO; + + *read_val = AD7091R_REG_RESULT_CONV_RESULT(val); + + return 0; +} + +static int ad7091r_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long m) +{ + struct ad7091r_state *st = iio_priv(iio_dev); + unsigned int read_val; + int ret; + + mutex_lock(&st->lock); + + switch (m) { + case IIO_CHAN_INFO_RAW: + if (st->mode != AD7091R_MODE_COMMAND) { + ret = -EBUSY; + goto unlock; + } + + ret = ad7091r_read_one(iio_dev, chan->channel, &read_val); + if (ret) + goto unlock; + + *val = read_val; + ret = IIO_VAL_INT; + break; + + default: + ret = -EINVAL; + break; + } + +unlock: + mutex_unlock(&st->lock); + return ret; +} + +static const struct iio_info ad7091r_info = { + .read_raw = ad7091r_read_raw, +}; + +static irqreturn_t ad7091r_event_handler(int irq, void *private) +{ + struct ad7091r_state *st = (struct ad7091r_state *) private; + struct iio_dev *iio_dev = dev_get_drvdata(st->dev); + unsigned int i, read_val; + int ret; + s64 timestamp = iio_get_time_ns(iio_dev); + + ret = regmap_read(st->map, AD7091R_REG_ALERT, &read_val); + if (ret) + return IRQ_HANDLED; + + for (i = 0; i < st->chip_info->num_channels; i++) { + if (read_val & BIT(i * 2)) + iio_push_event(iio_dev, + IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), timestamp); + if (read_val & BIT(i * 2 + 1)) + iio_push_event(iio_dev, + IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), timestamp); + } + + return IRQ_HANDLED; +} + +int ad7091r_probe(struct device *dev, const char *name, + const struct ad7091r_chip_info *chip_info, + struct regmap *map, int irq) +{ + struct iio_dev *iio_dev; + struct ad7091r_state *st; + int ret; + + iio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!iio_dev) + return -ENOMEM; + + st = iio_priv(iio_dev); + st->dev = dev; + st->chip_info = chip_info; + st->map = map; + + iio_dev->dev.parent = dev; + iio_dev->name = name; + iio_dev->info = &ad7091r_info; + iio_dev->modes = INDIO_DIRECT_MODE; + + iio_dev->num_channels = chip_info->num_channels; + iio_dev->channels = chip_info->channels; + + if (irq) { + ret = devm_request_threaded_irq(dev, irq, NULL, + ad7091r_event_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, name, st); + if (ret) + return ret; + } + + /* Use command mode by default to convert only desired channels*/ + ret = ad7091r_set_mode(st, AD7091R_MODE_COMMAND); + if (ret) + return ret; + + return devm_iio_device_register(dev, iio_dev); +} +EXPORT_SYMBOL_GPL(ad7091r_probe); + +static bool ad7091r_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AD7091R_REG_RESULT: + case AD7091R_REG_ALERT: + return false; + default: + return true; + } +} + +static bool ad7091r_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case AD7091R_REG_RESULT: + case AD7091R_REG_ALERT: + return true; + default: + return false; + } +} + +const struct regmap_config ad7091r_regmap_config = { + .reg_bits = 8, + .val_bits = 16, + .writeable_reg = ad7091r_writeable_reg, + .volatile_reg = ad7091r_volatile_reg, +}; +EXPORT_SYMBOL_GPL(ad7091r_regmap_config); + +MODULE_AUTHOR("Beniamin Bia "); +MODULE_DESCRIPTION("Analog Devices AD7091Rx multi-channel converters"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ad7091r-base.h b/drivers/iio/adc/ad7091r-base.h new file mode 100644 index 000000000000..b0b4fe01a681 --- /dev/null +++ b/drivers/iio/adc/ad7091r-base.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * AD7091RX Analog to Digital converter driver + * + * Copyright 2014-2019 Analog Devices Inc. + */ + +#ifndef __DRIVERS_IIO_ADC_AD7091R_BASE_H__ +#define __DRIVERS_IIO_ADC_AD7091R_BASE_H__ + +struct device; +struct ad7091r_state; + +struct ad7091r_chip_info { + unsigned int num_channels; + const struct iio_chan_spec *channels; +}; + +extern const struct regmap_config ad7091r_regmap_config; + +int ad7091r_probe(struct device *dev, const char *name, + const struct ad7091r_chip_info *chip_info, + struct regmap *map, int irq); + +#endif /* __DRIVERS_IIO_ADC_AD7091R_BASE_H__ */ diff --git a/drivers/iio/adc/ad7091r5.c b/drivers/iio/adc/ad7091r5.c new file mode 100644 index 000000000000..30ff0108a6ed --- /dev/null +++ b/drivers/iio/adc/ad7091r5.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AD7091R5 Analog to Digital converter driver + * + * Copyright 2014-2019 Analog Devices Inc. + */ + +#include +#include +#include +#include + +#include "ad7091r-base.h" + +static const struct iio_event_spec ad7091r5_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS), + }, +}; + +#define AD7091R_CHANNEL(idx, bits, ev, num_ev) { \ + .type = IIO_VOLTAGE, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .indexed = 1, \ + .channel = idx, \ + .event_spec = ev, \ + .num_event_specs = num_ev, \ +} +static const struct iio_chan_spec ad7091r5_channels_irq[] = { + AD7091R_CHANNEL(0, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), + AD7091R_CHANNEL(1, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), + AD7091R_CHANNEL(2, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), + AD7091R_CHANNEL(3, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), +}; + +static const struct iio_chan_spec ad7091r5_channels_noirq[] = { + AD7091R_CHANNEL(0, 12, NULL, 0), + AD7091R_CHANNEL(1, 12, NULL, 0), + AD7091R_CHANNEL(2, 12, NULL, 0), + AD7091R_CHANNEL(3, 12, NULL, 0), +}; + +static const struct ad7091r_chip_info ad7091r5_chip_info_irq = { + .channels = ad7091r5_channels_irq, + .num_channels = ARRAY_SIZE(ad7091r5_channels_irq), +}; + +static const struct ad7091r_chip_info ad7091r5_chip_info_noirq = { + .channels = ad7091r5_channels_noirq, + .num_channels = ARRAY_SIZE(ad7091r5_channels_noirq), +}; + +static int ad7091r5_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + const struct ad7091r_chip_info *chip_info; + struct regmap *map = devm_regmap_init_i2c(i2c, &ad7091r_regmap_config); + + if (IS_ERR(map)) + return PTR_ERR(map); + + if (i2c->irq) + chip_info = &ad7091r5_chip_info_irq; + else + chip_info = &ad7091r5_chip_info_noirq; + + return ad7091r_probe(&i2c->dev, id->name, chip_info, map, i2c->irq); +} + +static const struct of_device_id ad7091r5_dt_ids[] = { + { .compatible = "adi,ad7091r5" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ad7091r5_dt_ids); + +static const struct i2c_device_id ad7091r5_i2c_ids[] = { + {"ad7091r5", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, ad7091r5_i2c_ids); + +static struct i2c_driver ad7091r5_driver = { + .driver = { + .name = "ad7091r5", + .of_match_table = ad7091r5_dt_ids, + }, + .probe = ad7091r5_i2c_probe, + .id_table = ad7091r5_i2c_ids, +}; +module_i2c_driver(ad7091r5_driver); + +MODULE_AUTHOR("Beniamin Bia "); +MODULE_DESCRIPTION("Analog Devices AD7091R5 multi-channel ADC driver"); +MODULE_LICENSE("GPL v2"); From 260442cc5be4e652628f01ea6ac58f542e2c8e7a Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Fri, 15 Nov 2019 15:57:21 +0200 Subject: [PATCH 003/353] iio: adc: ad7091r5: Add scale and external VREF support The scale can now be obtained with the "in_voltage_scale" file. By default, the scale returned corresponds to the internal VREF of 2.5V. It is possible to use an external VREF (through the REFIN/REFOUT pin of the chip), by passing a regulator to the driver. The scale will then be calculated according to the voltage reported by the regulator. Signed-off-by: Paul Cercueil Co-developed-by: Beniamin Bia Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7091r-base.c | 38 ++++++++++++++++++++++++++++++++++ drivers/iio/adc/ad7091r-base.h | 1 + drivers/iio/adc/ad7091r5.c | 5 +++++ 3 files changed, 44 insertions(+) diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c index 854de7c654c2..33c40357bd5e 100644 --- a/drivers/iio/adc/ad7091r-base.c +++ b/drivers/iio/adc/ad7091r-base.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "ad7091r-base.h" @@ -42,6 +43,7 @@ enum ad7091r_mode { struct ad7091r_state { struct device *dev; struct regmap *map; + struct regulator *vref; const struct ad7091r_chip_info *chip_info; enum ad7091r_mode mode; struct mutex lock; /*lock to prevent concurent reads */ @@ -141,6 +143,21 @@ static int ad7091r_read_raw(struct iio_dev *iio_dev, ret = IIO_VAL_INT; break; + case IIO_CHAN_INFO_SCALE: + if (st->vref) { + ret = regulator_get_voltage(st->vref); + if (ret < 0) + goto unlock; + + *val = ret / 1000; + } else { + *val = st->chip_info->vref_mV; + } + + *val2 = chan->scan_type.realbits; + ret = IIO_VAL_FRACTIONAL_LOG2; + break; + default: ret = -EINVAL; break; @@ -183,6 +200,13 @@ static irqreturn_t ad7091r_event_handler(int irq, void *private) return IRQ_HANDLED; } +static void ad7091r_remove(void *data) +{ + struct ad7091r_state *st = data; + + regulator_disable(st->vref); +} + int ad7091r_probe(struct device *dev, const char *name, const struct ad7091r_chip_info *chip_info, struct regmap *map, int irq) @@ -216,6 +240,20 @@ int ad7091r_probe(struct device *dev, const char *name, return ret; } + st->vref = devm_regulator_get_optional(dev, "vref"); + if (IS_ERR(st->vref)) { + if (PTR_ERR(st->vref) == -EPROBE_DEFER) + return -EPROBE_DEFER; + st->vref = NULL; + } else { + ret = regulator_enable(st->vref); + if (ret) + return ret; + ret = devm_add_action_or_reset(dev, ad7091r_remove, st); + if (ret) + return ret; + } + /* Use command mode by default to convert only desired channels*/ ret = ad7091r_set_mode(st, AD7091R_MODE_COMMAND); if (ret) diff --git a/drivers/iio/adc/ad7091r-base.h b/drivers/iio/adc/ad7091r-base.h index b0b4fe01a681..509748aef9b1 100644 --- a/drivers/iio/adc/ad7091r-base.h +++ b/drivers/iio/adc/ad7091r-base.h @@ -14,6 +14,7 @@ struct ad7091r_state; struct ad7091r_chip_info { unsigned int num_channels; const struct iio_chan_spec *channels; + unsigned int vref_mV; }; extern const struct regmap_config ad7091r_regmap_config; diff --git a/drivers/iio/adc/ad7091r5.c b/drivers/iio/adc/ad7091r5.c index 30ff0108a6ed..9665679c3ea6 100644 --- a/drivers/iio/adc/ad7091r5.c +++ b/drivers/iio/adc/ad7091r5.c @@ -35,10 +35,13 @@ static const struct iio_event_spec ad7091r5_events[] = { #define AD7091R_CHANNEL(idx, bits, ev, num_ev) { \ .type = IIO_VOLTAGE, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .indexed = 1, \ .channel = idx, \ .event_spec = ev, \ .num_event_specs = num_ev, \ + .scan_type.storagebits = 16, \ + .scan_type.realbits = bits, \ } static const struct iio_chan_spec ad7091r5_channels_irq[] = { AD7091R_CHANNEL(0, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), @@ -57,11 +60,13 @@ static const struct iio_chan_spec ad7091r5_channels_noirq[] = { static const struct ad7091r_chip_info ad7091r5_chip_info_irq = { .channels = ad7091r5_channels_irq, .num_channels = ARRAY_SIZE(ad7091r5_channels_irq), + .vref_mV = 2500, }; static const struct ad7091r_chip_info ad7091r5_chip_info_noirq = { .channels = ad7091r5_channels_noirq, .num_channels = ARRAY_SIZE(ad7091r5_channels_noirq), + .vref_mV = 2500, }; static int ad7091r5_i2c_probe(struct i2c_client *i2c, From a00140b93340557c2d48d04fad3c6d31b06b1de8 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Fri, 15 Nov 2019 15:57:22 +0200 Subject: [PATCH 004/353] dt-binding: iio: Add documentation for AD7091R5 Documentation for AD7091R5 ADC was added. Signed-off-by: Beniamin Bia Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/adc/adi,ad7091r5.yaml | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml new file mode 100644 index 000000000000..31ffa275f5fa --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,ad7091r5.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AD7091R5 4-Channel 12-Bit ADC + +maintainers: + - Beniamin Bia + +description: | + Analog Devices AD7091R5 4-Channel 12-Bit ADC + https://www.analog.com/media/en/technical-documentation/data-sheets/ad7091r-5.pdf + +properties: + compatible: + enum: + - adi,ad7091r5 + + reg: + maxItems: 1 + + vref-supply: + description: + Phandle to the vref power supply + + interrupts: + maxItems: 1 + + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + adc@2f { + compatible = "adi,ad7091r5"; + reg = <0x2f>; + + interrupts = <25 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpio>; + }; + }; +... From e552ef5195683edaa059d28a56bec7f49a9ae0ec Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Fri, 15 Nov 2019 15:57:23 +0200 Subject: [PATCH 005/353] MAINTAINERS: add entry for AD7091R5 driver Add Beniamin Bia as a maintainer for AD7091R5 ADC. Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 99def8472f3f..3ef731fc753b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -893,6 +893,14 @@ S: Supported F: drivers/iio/dac/ad5758.c F: Documentation/devicetree/bindings/iio/dac/ad5758.txt +ANALOG DEVICES INC AD7091R5 DRIVER +M: Beniamin Bia +L: linux-iio@vger.kernel.org +W: http://ez.analog.com/community/linux-device-drivers +S: Supported +F: drivers/iio/adc/ad7091r5.c +F: Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml + ANALOG DEVICES INC AD7124 DRIVER M: Stefan Popa L: linux-iio@vger.kernel.org From b95ed406278f7588a5504ef94cb526bb8d7f70ff Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Maneyrol Date: Fri, 15 Nov 2019 15:06:21 +0100 Subject: [PATCH 006/353] iio: imu: inv_mpu6050: delete not existing MPU9150 spi support MPU9150 is i2c only. Update Kconfig to delete in description chips that are i2c or spi only. Signed-off-by: Jean-Baptiste Maneyrol Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/Kconfig | 6 +++--- drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index e4c4c12236a7..963a0cafe0cb 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -14,7 +14,7 @@ config INV_MPU6050_I2C select INV_MPU6050_IIO select REGMAP_I2C help - This driver supports the Invensense MPU6000/6050/6500/6515, + This driver supports the Invensense MPU6050/6500/6515, MPU9150/9250/9255 and ICM20608/20602 motion tracking devices over I2C. This driver can be built as a module. The module will be called @@ -26,8 +26,8 @@ config INV_MPU6050_SPI select INV_MPU6050_IIO select REGMAP_SPI help - This driver supports the Invensense MPU6000/6050/6500/6515, - MPU9150/9250/9255 and ICM20608/20602 motion tracking devices + This driver supports the Invensense MPU6000/6500/6515, + MPU9250/9255 and ICM20608/20602 motion tracking devices over SPI. This driver can be built as a module. The module will be called inv-mpu6050-spi. diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c index 142692fc0758..ec102d5a5c77 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c @@ -74,7 +74,6 @@ static int inv_mpu_probe(struct spi_device *spi) static const struct spi_device_id inv_mpu_id[] = { {"mpu6000", INV_MPU6000}, {"mpu6500", INV_MPU6500}, - {"mpu9150", INV_MPU9150}, {"mpu9250", INV_MPU9250}, {"mpu9255", INV_MPU9255}, {"icm20608", INV_ICM20608}, From a2587eb032f1679dd695b9e5113bcb6b52e46e0a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Maneyrol Date: Fri, 15 Nov 2019 15:06:22 +0100 Subject: [PATCH 007/353] iio: imu: inv_mpu6050: add support of MPU9150 magnetometer Add support for driving MPU9150 magnetometer (AK8975) from mpu. Signed-off-by: Jean-Baptiste Maneyrol Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 57 ++++++++++--- drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 2 + drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c | 80 +++++++++++++------ drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 1 + 4 files changed, 104 insertions(+), 36 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 45e77b308238..23c0557891a0 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -914,6 +914,33 @@ static const unsigned long inv_mpu_scan_masks[] = { .ext_info = inv_ext_info, \ } +static const struct iio_chan_spec inv_mpu9150_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP), + /* + * Note that temperature should only be via polled reading only, + * not the final scan elements output. + */ + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) + | BIT(IIO_CHAN_INFO_OFFSET) + | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = -1, + }, + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), + + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X), + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y), + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z), + + /* Magnetometer resolution is 13 bits */ + INV_MPU9X50_MAGN_CHAN(IIO_MOD_X, 13, INV_MPU9X50_SCAN_MAGN_X), + INV_MPU9X50_MAGN_CHAN(IIO_MOD_Y, 13, INV_MPU9X50_SCAN_MAGN_Y), + INV_MPU9X50_MAGN_CHAN(IIO_MOD_Z, 13, INV_MPU9X50_SCAN_MAGN_Z), +}; + static const struct iio_chan_spec inv_mpu9250_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP), /* @@ -1323,21 +1350,16 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, inv_mpu_bus_setup(indio_dev); switch (chip_type) { + case INV_MPU9150: + indio_dev->channels = inv_mpu9150_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_mpu9150_channels); + indio_dev->available_scan_masks = inv_mpu9x50_scan_masks; + break; case INV_MPU9250: case INV_MPU9255: - /* - * Use magnetometer inside the chip only if there is no i2c - * auxiliary device in use. - */ - if (!st->magn_disabled) { - indio_dev->channels = inv_mpu9250_channels; - indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels); - indio_dev->available_scan_masks = inv_mpu9x50_scan_masks; - } else { - indio_dev->channels = inv_mpu_channels; - indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); - indio_dev->available_scan_masks = inv_mpu_scan_masks; - } + indio_dev->channels = inv_mpu9250_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels); + indio_dev->available_scan_masks = inv_mpu9x50_scan_masks; break; case INV_ICM20602: indio_dev->channels = inv_icm20602_channels; @@ -1350,6 +1372,15 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, indio_dev->available_scan_masks = inv_mpu_scan_masks; break; } + /* + * Use magnetometer inside the chip only if there is no i2c + * auxiliary device in use. Otherwise Going back to 6-axis only. + */ + if (st->magn_disabled) { + indio_dev->channels = inv_mpu_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); + indio_dev->available_scan_masks = inv_mpu_scan_masks; + } indio_dev->info = &mpu_info; indio_dev->modes = INDIO_BUFFER_TRIGGERED; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index 389cc8505e0e..f47a28b4be23 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -77,6 +77,7 @@ static bool inv_mpu_i2c_aux_bus(struct device *dev) case INV_ICM20602: /* no i2c auxiliary bus on the chip */ return false; + case INV_MPU9150: case INV_MPU9250: case INV_MPU9255: if (st->magn_disabled) @@ -102,6 +103,7 @@ static int inv_mpu_magn_disable(struct iio_dev *indio_dev) struct device_node *mux_node; switch (st->chip_type) { + case INV_MPU9150: case INV_MPU9250: case INV_MPU9255: mux_node = of_get_child_by_name(dev->of_node, "i2c-gate"); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c index 02735af152c8..4f192352521e 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c @@ -12,7 +12,9 @@ #include "inv_mpu_magn.h" /* - * MPU9250 magnetometer is an AKM AK8963 chip on I2C aux bus + * MPU9xxx magnetometer are AKM chips on I2C aux bus + * MPU9150 is AK8975 + * MPU9250 is AK8963 */ #define INV_MPU_MAGN_I2C_ADDR 0x0C @@ -33,10 +35,10 @@ #define INV_MPU_MAGN_BITS_MODE_PWDN 0x00 #define INV_MPU_MAGN_BITS_MODE_SINGLE 0x01 #define INV_MPU_MAGN_BITS_MODE_FUSE 0x0F -#define INV_MPU_MAGN_BIT_OUTPUT_BIT 0x10 +#define INV_MPU9250_MAGN_BIT_OUTPUT_BIT 0x10 -#define INV_MPU_MAGN_REG_CNTL2 0x0B -#define INV_MPU_MAGN_BIT_SRST 0x01 +#define INV_MPU9250_MAGN_REG_CNTL2 0x0B +#define INV_MPU9250_MAGN_BIT_SRST 0x01 #define INV_MPU_MAGN_REG_ASAX 0x10 #define INV_MPU_MAGN_REG_ASAY 0x11 @@ -48,6 +50,7 @@ static bool inv_magn_supported(const struct inv_mpu6050_state *st) { switch (st->chip_type) { + case INV_MPU9150: case INV_MPU9250: case INV_MPU9255: return true; @@ -61,6 +64,7 @@ static int inv_magn_init(struct inv_mpu6050_state *st) { uint8_t val; uint8_t asa[3]; + int32_t sensitivity; int ret; /* check whoami */ @@ -71,12 +75,19 @@ static int inv_magn_init(struct inv_mpu6050_state *st) if (val != INV_MPU_MAGN_BITS_WIA) return -ENODEV; - /* reset chip */ - ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR, - INV_MPU_MAGN_REG_CNTL2, - INV_MPU_MAGN_BIT_SRST); - if (ret) - return ret; + /* software reset for MPU925x only */ + switch (st->chip_type) { + case INV_MPU9250: + case INV_MPU9255: + ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR, + INV_MPU9250_MAGN_REG_CNTL2, + INV_MPU9250_MAGN_BIT_SRST); + if (ret) + return ret; + break; + default: + break; + } /* read fuse ROM data */ ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR, @@ -97,6 +108,25 @@ static int inv_magn_init(struct inv_mpu6050_state *st) if (ret) return ret; + /* + * Sensor sentivity + * 1 uT = 0.01 G and value is in micron (1e6) + * sensitvity = x uT * 0.01 * 1e6 + */ + switch (st->chip_type) { + case INV_MPU9150: + /* sensor sensitivity is 0.3 uT */ + sensitivity = 3000; + break; + case INV_MPU9250: + case INV_MPU9255: + /* sensor sensitivity in 16 bits mode: 0.15 uT */ + sensitivity = 1500; + break; + default: + return -EINVAL; + } + /* * Sensitivity adjustement and scale to Gauss * @@ -104,16 +134,11 @@ static int inv_magn_init(struct inv_mpu6050_state *st) * Factor simplification: * Hadj = H * ((ASA + 128) / 256) * - * Sensor sentivity - * 0.15 uT in 16 bits mode - * 1 uT = 0.01 G and value is in micron (1e6) - * sensitvity = 0.15 uT * 0.01 * 1e6 - * - * raw_to_gauss = Hadj * 1500 + * raw_to_gauss = Hadj * sensitivity */ - st->magn_raw_to_gauss[0] = (((int32_t)asa[0] + 128) * 1500) / 256; - st->magn_raw_to_gauss[1] = (((int32_t)asa[1] + 128) * 1500) / 256; - st->magn_raw_to_gauss[2] = (((int32_t)asa[2] + 128) * 1500) / 256; + st->magn_raw_to_gauss[0] = (((int32_t)asa[0] + 128) * sensitivity) / 256; + st->magn_raw_to_gauss[1] = (((int32_t)asa[1] + 128) * sensitivity) / 256; + st->magn_raw_to_gauss[2] = (((int32_t)asa[2] + 128) * sensitivity) / 256; return 0; } @@ -129,6 +154,7 @@ static int inv_magn_init(struct inv_mpu6050_state *st) */ int inv_mpu_magn_probe(struct inv_mpu6050_state *st) { + uint8_t val; int ret; /* quit if chip is not supported */ @@ -179,10 +205,17 @@ int inv_mpu_magn_probe(struct inv_mpu6050_state *st) if (ret) return ret; - /* add 16 bits mode */ - ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_DO(1), - INV_MPU_MAGN_BITS_MODE_SINGLE | - INV_MPU_MAGN_BIT_OUTPUT_BIT); + /* add 16 bits mode for MPU925x */ + val = INV_MPU_MAGN_BITS_MODE_SINGLE; + switch (st->chip_type) { + case INV_MPU9250: + case INV_MPU9255: + val |= INV_MPU9250_MAGN_BIT_OUTPUT_BIT; + break; + default: + break; + } + ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_DO(1), val); if (ret) return ret; @@ -237,6 +270,7 @@ int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st) /* fill magnetometer orientation */ switch (st->chip_type) { + case INV_MPU9150: case INV_MPU9250: case INV_MPU9255: /* x <- y */ diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c index d7d951927a44..a9c75bc62f18 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c @@ -50,6 +50,7 @@ static void inv_scan_query(struct iio_dev *indio_dev) struct inv_mpu6050_state *st = iio_priv(indio_dev); switch (st->chip_type) { + case INV_MPU9150: case INV_MPU9250: case INV_MPU9255: return inv_scan_query_mpu9x50(indio_dev); From a33db9475a3c7b6855c67d144dfa93a623b66cec Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 13 Nov 2019 11:09:38 +0100 Subject: [PATCH 008/353] iio: adc: max9611: Make enum relations more future proof MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The relations between enum values and array indices values are currently not enforced by the code, which makes them fragile w.r.t. future changes. Fix this by: 1. Using designated array initializers, to make sure array indices and enums values match, 2. Linking max9611_csa_gain enum values to the corresponding max9611_conf_ids enum values, as the latter is cast to the former in max9611_read_csa_voltage(). No change in generated code. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Acked-by: Jacopo Mondi Signed-off-by: Jonathan Cameron --- drivers/iio/adc/max9611.c | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/drivers/iio/adc/max9611.c b/drivers/iio/adc/max9611.c index da073d72f649..bf76dfb3f2c9 100644 --- a/drivers/iio/adc/max9611.c +++ b/drivers/iio/adc/max9611.c @@ -109,22 +109,17 @@ enum max9611_conf_ids { * where data shall be read from */ static const unsigned int max9611_mux_conf[][2] = { - /* CONF_SENSE_1x */ - { MAX9611_MUX_SENSE_1x, MAX9611_REG_CSA_DATA }, - /* CONF_SENSE_4x */ - { MAX9611_MUX_SENSE_4x, MAX9611_REG_CSA_DATA }, - /* CONF_SENSE_8x */ - { MAX9611_MUX_SENSE_8x, MAX9611_REG_CSA_DATA }, - /* CONF_IN_VOLT */ - { MAX9611_INPUT_VOLT, MAX9611_REG_RS_DATA }, - /* CONF_TEMP */ - { MAX9611_MUX_TEMP, MAX9611_REG_TEMP_DATA }, + [CONF_SENSE_1x] = { MAX9611_MUX_SENSE_1x, MAX9611_REG_CSA_DATA }, + [CONF_SENSE_4x] = { MAX9611_MUX_SENSE_4x, MAX9611_REG_CSA_DATA }, + [CONF_SENSE_8x] = { MAX9611_MUX_SENSE_8x, MAX9611_REG_CSA_DATA }, + [CONF_IN_VOLT] = { MAX9611_INPUT_VOLT, MAX9611_REG_RS_DATA }, + [CONF_TEMP] = { MAX9611_MUX_TEMP, MAX9611_REG_TEMP_DATA }, }; enum max9611_csa_gain { - CSA_GAIN_1x, - CSA_GAIN_4x, - CSA_GAIN_8x, + CSA_GAIN_1x = CONF_SENSE_1x, + CSA_GAIN_4x = CONF_SENSE_4x, + CSA_GAIN_8x = CONF_SENSE_8x, }; enum max9611_csa_gain_params { @@ -142,18 +137,9 @@ enum max9611_csa_gain_params { * value; use this structure to retrieve the correct LSB and offset values. */ static const unsigned int max9611_gain_conf[][2] = { - { /* [0] CSA_GAIN_1x */ - MAX9611_CSA_1X_LSB_nV, - MAX9611_CSA_1X_OFFS_RAW, - }, - { /* [1] CSA_GAIN_4x */ - MAX9611_CSA_4X_LSB_nV, - MAX9611_CSA_4X_OFFS_RAW, - }, - { /* [2] CSA_GAIN_8x */ - MAX9611_CSA_8X_LSB_nV, - MAX9611_CSA_8X_OFFS_RAW, - }, + [CSA_GAIN_1x] = { MAX9611_CSA_1X_LSB_nV, MAX9611_CSA_1X_OFFS_RAW, }, + [CSA_GAIN_4x] = { MAX9611_CSA_4X_LSB_nV, MAX9611_CSA_4X_OFFS_RAW, }, + [CSA_GAIN_8x] = { MAX9611_CSA_8X_LSB_nV, MAX9611_CSA_8X_OFFS_RAW, }, }; enum max9611_chan_addrs { From 6a9afcb198b4de323485c0ee94ff09f653012d4b Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 22 Nov 2019 15:24:11 +0200 Subject: [PATCH 009/353] iio: imu: adis: rename txrx_lock -> state_lock The lock can be extended a bit to protect other elements that are not particular to just TX/RX. Another idea would have been to just add a new `state_lock`, but that would mean 2 locks which would be redundant, and probably cause more potential for dead-locks. What will be done in the next patches, will be to add some unlocked versions for read/write_reg functions. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis.c | 10 +++++----- drivers/iio/imu/adis_buffer.c | 4 ++-- include/linux/iio/imu/adis.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 85de565a4e80..db562fec79b2 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -70,7 +70,7 @@ int adis_write_reg(struct adis *adis, unsigned int reg, }, }; - mutex_lock(&adis->txrx_lock); + mutex_lock(&adis->state_lock); spi_message_init(&msg); @@ -114,7 +114,7 @@ int adis_write_reg(struct adis *adis, unsigned int reg, } out_unlock: - mutex_unlock(&adis->txrx_lock); + mutex_unlock(&adis->state_lock); return ret; } @@ -166,7 +166,7 @@ int adis_read_reg(struct adis *adis, unsigned int reg, }, }; - mutex_lock(&adis->txrx_lock); + mutex_lock(&adis->state_lock); spi_message_init(&msg); if (adis->current_page != page) { @@ -211,7 +211,7 @@ int adis_read_reg(struct adis *adis, unsigned int reg, } out_unlock: - mutex_unlock(&adis->txrx_lock); + mutex_unlock(&adis->state_lock); return ret; } @@ -438,7 +438,7 @@ EXPORT_SYMBOL_GPL(adis_single_conversion); int adis_init(struct adis *adis, struct iio_dev *indio_dev, struct spi_device *spi, const struct adis_data *data) { - mutex_init(&adis->txrx_lock); + mutex_init(&adis->state_lock); adis->spi = spi; adis->data = data; iio_device_set_drvdata(indio_dev, adis); diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c index 4998a89d083d..3f4dd5c00b03 100644 --- a/drivers/iio/imu/adis_buffer.c +++ b/drivers/iio/imu/adis_buffer.c @@ -129,7 +129,7 @@ static irqreturn_t adis_trigger_handler(int irq, void *p) return -ENOMEM; if (adis->data->has_paging) { - mutex_lock(&adis->txrx_lock); + mutex_lock(&adis->state_lock); if (adis->current_page != 0) { adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); adis->tx[1] = 0; @@ -144,7 +144,7 @@ static irqreturn_t adis_trigger_handler(int irq, void *p) if (adis->data->has_paging) { adis->current_page = 0; - mutex_unlock(&adis->txrx_lock); + mutex_unlock(&adis->state_lock); } iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer, diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 92aae14593bf..100b5d1cebf1 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -61,7 +61,7 @@ struct adis { const struct adis_data *data; struct adis_burst *burst; - struct mutex txrx_lock; + struct mutex state_lock; struct spi_message msg; struct spi_transfer *xfer; unsigned int current_page; From 770d465619423a946248018ea39ed9a74c8f2ff4 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 22 Nov 2019 15:24:12 +0200 Subject: [PATCH 010/353] iio: imu: adis: add unlocked read/write function versions This will allow more flexible control to group reads & writes into a single lock (particularly the state_lock). The end-goal is to remove the indio_dev->mlock usage, and the simplest fix would have been to just add another lock, which would not be a good idea on the long-run. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis.c | 35 +++++------ include/linux/iio/imu/adis.h | 116 ++++++++++++++++++++++++++++++++++- 2 files changed, 130 insertions(+), 21 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index db562fec79b2..2f518e6c727d 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -26,7 +26,14 @@ #define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0) #define ADIS_GLOB_CMD_SW_RESET BIT(7) -int adis_write_reg(struct adis *adis, unsigned int reg, +/** + * __adis_write_reg() - write N bytes to register (unlocked version) + * @adis: The adis device + * @reg: The address of the lower of the two registers + * @value: The value to write to device (up to 4 bytes) + * @size: The size of the @value (in bytes) + */ +int __adis_write_reg(struct adis *adis, unsigned int reg, unsigned int value, unsigned int size) { unsigned int page = reg / ADIS_PAGE_SIZE; @@ -70,8 +77,6 @@ int adis_write_reg(struct adis *adis, unsigned int reg, }, }; - mutex_lock(&adis->state_lock); - spi_message_init(&msg); if (adis->current_page != page) { @@ -96,8 +101,7 @@ int adis_write_reg(struct adis *adis, unsigned int reg, adis->tx[3] = value & 0xff; break; default: - ret = -EINVAL; - goto out_unlock; + return -EINVAL; } xfers[size].cs_change = 0; @@ -113,20 +117,18 @@ int adis_write_reg(struct adis *adis, unsigned int reg, adis->current_page = page; } -out_unlock: - mutex_unlock(&adis->state_lock); - return ret; } -EXPORT_SYMBOL_GPL(adis_write_reg); +EXPORT_SYMBOL_GPL(__adis_write_reg); /** - * adis_read_reg() - read 2 bytes from a 16-bit register + * __adis_read_reg() - read N bytes from register (unlocked version) * @adis: The adis device * @reg: The address of the lower of the two registers * @val: The value read back from the device + * @size: The size of the @val buffer */ -int adis_read_reg(struct adis *adis, unsigned int reg, +int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val, unsigned int size) { unsigned int page = reg / ADIS_PAGE_SIZE; @@ -166,7 +168,6 @@ int adis_read_reg(struct adis *adis, unsigned int reg, }, }; - mutex_lock(&adis->state_lock); spi_message_init(&msg); if (adis->current_page != page) { @@ -188,15 +189,14 @@ int adis_read_reg(struct adis *adis, unsigned int reg, spi_message_add_tail(&xfers[3], &msg); break; default: - ret = -EINVAL; - goto out_unlock; + return -EINVAL; } ret = spi_sync(adis->spi, &msg); if (ret) { dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n", reg, ret); - goto out_unlock; + return ret; } else { adis->current_page = page; } @@ -210,12 +210,9 @@ int adis_read_reg(struct adis *adis, unsigned int reg, break; } -out_unlock: - mutex_unlock(&adis->state_lock); - return ret; } -EXPORT_SYMBOL_GPL(adis_read_reg); +EXPORT_SYMBOL_GPL(__adis_read_reg); #ifdef CONFIG_DEBUG_FS diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 100b5d1cebf1..38ebe41092e1 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -75,11 +75,123 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev, struct spi_device *spi, const struct adis_data *data); int adis_reset(struct adis *adis); -int adis_write_reg(struct adis *adis, unsigned int reg, +int __adis_write_reg(struct adis *adis, unsigned int reg, unsigned int val, unsigned int size); -int adis_read_reg(struct adis *adis, unsigned int reg, +int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val, unsigned int size); +/** + * __adis_write_reg_8() - Write single byte to a register (unlocked) + * @adis: The adis device + * @reg: The address of the register to be written + * @value: The value to write + */ +static inline int __adis_write_reg_8(struct adis *adis, unsigned int reg, + uint8_t val) +{ + return __adis_write_reg(adis, reg, val, 1); +} + +/** + * __adis_write_reg_16() - Write 2 bytes to a pair of registers (unlocked) + * @adis: The adis device + * @reg: The address of the lower of the two registers + * @value: Value to be written + */ +static inline int __adis_write_reg_16(struct adis *adis, unsigned int reg, + uint16_t val) +{ + return __adis_write_reg(adis, reg, val, 2); +} + +/** + * __adis_write_reg_32() - write 4 bytes to four registers (unlocked) + * @adis: The adis device + * @reg: The address of the lower of the four register + * @value: Value to be written + */ +static inline int __adis_write_reg_32(struct adis *adis, unsigned int reg, + uint32_t val) +{ + return __adis_write_reg(adis, reg, val, 4); +} + +/** + * __adis_read_reg_16() - read 2 bytes from a 16-bit register (unlocked) + * @adis: The adis device + * @reg: The address of the lower of the two registers + * @val: The value read back from the device + */ +static inline int __adis_read_reg_16(struct adis *adis, unsigned int reg, + uint16_t *val) +{ + unsigned int tmp; + int ret; + + ret = __adis_read_reg(adis, reg, &tmp, 2); + if (ret == 0) + *val = tmp; + + return ret; +} + +/** + * __adis_read_reg_32() - read 4 bytes from a 32-bit register (unlocked) + * @adis: The adis device + * @reg: The address of the lower of the two registers + * @val: The value read back from the device + */ +static inline int __adis_read_reg_32(struct adis *adis, unsigned int reg, + uint32_t *val) +{ + unsigned int tmp; + int ret; + + ret = __adis_read_reg(adis, reg, &tmp, 4); + if (ret == 0) + *val = tmp; + + return ret; +} + +/** + * adis_write_reg() - write N bytes to register + * @adis: The adis device + * @reg: The address of the lower of the two registers + * @value: The value to write to device (up to 4 bytes) + * @size: The size of the @value (in bytes) + */ +static inline int adis_write_reg(struct adis *adis, unsigned int reg, + unsigned int val, unsigned int size) +{ + int ret; + + mutex_lock(&adis->state_lock); + ret = __adis_write_reg(adis, reg, val, size); + mutex_unlock(&adis->state_lock); + + return ret; +} + +/** + * adis_read_reg() - read N bytes from register + * @adis: The adis device + * @reg: The address of the lower of the two registers + * @val: The value read back from the device + * @size: The size of the @val buffer + */ +static int adis_read_reg(struct adis *adis, unsigned int reg, + unsigned int *val, unsigned int size) +{ + int ret; + + mutex_lock(&adis->state_lock); + ret = __adis_read_reg(adis, reg, val, size); + mutex_unlock(&adis->state_lock); + + return ret; +} + /** * adis_write_reg_8() - Write single byte to a register * @adis: The adis device From 100bfa38c8cb81ccbbd17ee4f0c1164f455f6039 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 22 Nov 2019 15:24:13 +0200 Subject: [PATCH 011/353] iio: imu: adis[16480]: group RW into a single lock in adis_enable_irq() The adis_enable_irq() does a read & a write. This change keeps a lock for the duration of both operations vs for each op. The change is also needed in adis16480, since that has it's own implementation for adis_enable_irq(). Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis.c | 17 +++++++++++------ drivers/iio/imu/adis16480.c | 4 ++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 2f518e6c727d..5cf7a15be6ee 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -250,12 +250,16 @@ int adis_enable_irq(struct adis *adis, bool enable) int ret = 0; uint16_t msc; - if (adis->data->enable_irq) - return adis->data->enable_irq(adis, enable); + mutex_lock(&adis->state_lock); - ret = adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc); + if (adis->data->enable_irq) { + ret = adis->data->enable_irq(adis, enable); + goto out_unlock; + } + + ret = __adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc); if (ret) - goto error_ret; + goto out_unlock; msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH; msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2; @@ -264,9 +268,10 @@ int adis_enable_irq(struct adis *adis, bool enable) else msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN; - ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc); + ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc); -error_ret: +out_unlock: + mutex_unlock(&adis->state_lock); return ret; } EXPORT_SYMBOL(adis_enable_irq); diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index 748f8bbf184d..e943039c3f98 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -947,14 +947,14 @@ static int adis16480_enable_irq(struct adis *adis, bool enable) uint16_t val; int ret; - ret = adis_read_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, &val); + ret = __adis_read_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, &val); if (ret) return ret; val &= ~ADIS16480_DRDY_EN_MSK; val |= ADIS16480_DRDY_EN(enable); - return adis_write_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, val); + return __adis_write_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, val); } static int adis16480_initial_setup(struct iio_dev *indio_dev) From 6a4d6a7d6588d8c15501542da786ebff6602475c Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 22 Nov 2019 15:24:14 +0200 Subject: [PATCH 012/353] iio: imu: adis: create an unlocked version of adis_check_status() This one also gets re-used in certain operations, so it makes sense to have an unlocked version of this to group it with other reads/writes/operations to have a single lock for the whole state change. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis.c | 8 ++++---- include/linux/iio/imu/adis.h | 13 ++++++++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 5cf7a15be6ee..b63d6e6f5415 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -277,18 +277,18 @@ out_unlock: EXPORT_SYMBOL(adis_enable_irq); /** - * adis_check_status() - Check the device for error conditions + * __adis_check_status() - Check the device for error conditions (unlocked) * @adis: The adis device * * Returns 0 on success, a negative error code otherwise */ -int adis_check_status(struct adis *adis) +int __adis_check_status(struct adis *adis) { uint16_t status; int ret; int i; - ret = adis_read_reg_16(adis, adis->data->diag_stat_reg, &status); + ret = __adis_read_reg_16(adis, adis->data->diag_stat_reg, &status); if (ret) return ret; @@ -306,7 +306,7 @@ int adis_check_status(struct adis *adis) return -EIO; } -EXPORT_SYMBOL_GPL(adis_check_status); +EXPORT_SYMBOL_GPL(__adis_check_status); /** * adis_reset() - Reset the device diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 38ebe41092e1..db759957e1c1 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -267,7 +267,18 @@ static inline int adis_read_reg_32(struct adis *adis, unsigned int reg, } int adis_enable_irq(struct adis *adis, bool enable); -int adis_check_status(struct adis *adis); +int __adis_check_status(struct adis *adis); + +static inline int adis_check_status(struct adis *adis) +{ + int ret; + + mutex_lock(&adis->state_lock); + ret = __adis_check_status(adis); + mutex_unlock(&adis->state_lock); + + return ret; +} int adis_initial_startup(struct adis *adis); From 762ab093cbe26451175a5a63ea06c971bf973525 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 22 Nov 2019 15:24:15 +0200 Subject: [PATCH 013/353] iio: imu: adis: create an unlocked version of adis_reset() The reset routine may also be important to be protected by the state-lock and grouped with other operations, so create an unlocked version, so that this can be done. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis.c | 8 ++++---- include/linux/iio/imu/adis.h | 19 ++++++++++++++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index b63d6e6f5415..615f174f0e6e 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -309,23 +309,23 @@ int __adis_check_status(struct adis *adis) EXPORT_SYMBOL_GPL(__adis_check_status); /** - * adis_reset() - Reset the device + * __adis_reset() - Reset the device (unlocked version) * @adis: The adis device * * Returns 0 on success, a negative error code otherwise */ -int adis_reset(struct adis *adis) +int __adis_reset(struct adis *adis) { int ret; - ret = adis_write_reg_8(adis, adis->data->glob_cmd_reg, + ret = __adis_write_reg_8(adis, adis->data->glob_cmd_reg, ADIS_GLOB_CMD_SW_RESET); if (ret) dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret); return ret; } -EXPORT_SYMBOL_GPL(adis_reset); +EXPORT_SYMBOL_GPL(__adis_reset); static int adis_self_test(struct adis *adis) { diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index db759957e1c1..4b5bc0e06e69 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -73,7 +73,24 @@ struct adis { int adis_init(struct adis *adis, struct iio_dev *indio_dev, struct spi_device *spi, const struct adis_data *data); -int adis_reset(struct adis *adis); +int __adis_reset(struct adis *adis); + +/** + * adis_reset() - Reset the device + * @adis: The adis device + * + * Returns 0 on success, a negative error code otherwise + */ +static inline int adis_reset(struct adis *adis) +{ + int ret; + + mutex_lock(&adis->state_lock); + ret = __adis_reset(adis); + mutex_unlock(&adis->state_lock); + + return ret; +} int __adis_write_reg(struct adis *adis, unsigned int reg, unsigned int val, unsigned int size); From cb5a07f1f15cc3fd7e12bfdd48ba0e9fb585ea5e Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 22 Nov 2019 15:24:16 +0200 Subject: [PATCH 014/353] iio: imu: adis: protect initial startup routine with state lock The initial startup routine is called by some ADIS drivers during probe, and before registering with IIO. Normally, userspace should not be able to do any access to the device (as there shouldn't be any available). This change extends the state lock to the entire initial-startup routine. Behaviourally nothing should change, but this should make the library function a bit more robust. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 615f174f0e6e..10b8922fd51b 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -331,7 +331,7 @@ static int adis_self_test(struct adis *adis) { int ret; - ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg, + ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, adis->data->self_test_mask); if (ret) { dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n", @@ -341,10 +341,10 @@ static int adis_self_test(struct adis *adis) msleep(adis->data->startup_delay); - ret = adis_check_status(adis); + ret = __adis_check_status(adis); if (adis->data->self_test_no_autoclear) - adis_write_reg_16(adis, adis->data->msc_ctrl_reg, 0x00); + __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, 0x00); return ret; } @@ -362,19 +362,23 @@ int adis_initial_startup(struct adis *adis) { int ret; + mutex_lock(&adis->state_lock); + ret = adis_self_test(adis); if (ret) { dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n"); - adis_reset(adis); + __adis_reset(adis); msleep(adis->data->startup_delay); ret = adis_self_test(adis); if (ret) { dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n"); - return ret; + goto out_unlock; } } - return 0; +out_unlock: + mutex_unlock(&adis->state_lock); + return ret; } EXPORT_SYMBOL_GPL(adis_initial_startup); From c5485a5d6a5f7d00ca4aba6698526c5ae3f2a1a2 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 22 Nov 2019 15:24:17 +0200 Subject: [PATCH 015/353] iio: imu: adis: group single conversion under a single state lock The single conversion function does a series of reads + writes. This change extends the use of the state_lock for the entire set of operations. Previously, indio_dev's mlock was used. This change also removes the use of this lock. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 10b8922fd51b..c53f3ed3cb97 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -404,15 +404,15 @@ int adis_single_conversion(struct iio_dev *indio_dev, unsigned int uval; int ret; - mutex_lock(&indio_dev->mlock); + mutex_lock(&adis->state_lock); - ret = adis_read_reg(adis, chan->address, &uval, + ret = __adis_read_reg(adis, chan->address, &uval, chan->scan_type.storagebits / 8); if (ret) goto err_unlock; if (uval & error_mask) { - ret = adis_check_status(adis); + ret = __adis_check_status(adis); if (ret) goto err_unlock; } @@ -424,7 +424,7 @@ int adis_single_conversion(struct iio_dev *indio_dev, ret = IIO_VAL_INT; err_unlock: - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&adis->state_lock); return ret; } EXPORT_SYMBOL_GPL(adis_single_conversion); From ce476cd18aaea91ee31b991774553ba5239c9ee2 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 22 Nov 2019 15:24:18 +0200 Subject: [PATCH 016/353] iio: imu: adis16400: rework locks using ADIS library's state lock This change removes the use of indio_dev's mlock in favor using the state lock from the ADIS library. The set_freq() & get_freq() hooks are unlocked, so they require specific locking. That is because in some cases the get_freq() hook is used in combination with adis16400_set_filter(). In cases where only one read/write is done, the functions that hold the state lock are used. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis16400.c | 51 ++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 44e46dc96e00..662cb5367c11 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -162,6 +162,7 @@ struct adis16400_chip_info { unsigned int accel_scale_micro; int temp_scale_nano; int temp_offset; + /* set_freq() & get_freq() need to avoid using ADIS lib's state lock */ int (*set_freq)(struct adis16400_state *st, unsigned int freq); int (*get_freq)(struct adis16400_state *st); }; @@ -326,7 +327,7 @@ static int adis16334_get_freq(struct adis16400_state *st) int ret; uint16_t t; - ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); + ret = __adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); if (ret) return ret; @@ -350,7 +351,7 @@ static int adis16334_set_freq(struct adis16400_state *st, unsigned int freq) t <<= ADIS16334_RATE_DIV_SHIFT; t |= ADIS16334_RATE_INT_CLK; - return adis_write_reg_16(&st->adis, ADIS16400_SMPL_PRD, t); + return __adis_write_reg_16(&st->adis, ADIS16400_SMPL_PRD, t); } static int adis16400_get_freq(struct adis16400_state *st) @@ -358,7 +359,7 @@ static int adis16400_get_freq(struct adis16400_state *st) int sps, ret; uint16_t t; - ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); + ret = __adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); if (ret) return ret; @@ -390,7 +391,7 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq) else st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST; - return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val); + return __adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val); } static const unsigned int adis16400_3db_divisors[] = { @@ -404,7 +405,7 @@ static const unsigned int adis16400_3db_divisors[] = { [7] = 200, /* Not a valid setting */ }; -static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) +static int __adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) { struct adis16400_state *st = iio_priv(indio_dev); uint16_t val16; @@ -415,11 +416,11 @@ static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) break; } - ret = adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16); + ret = __adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16); if (ret) return ret; - ret = adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG, + ret = __adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG, (val16 & ~0x07) | i); return ret; } @@ -507,32 +508,31 @@ static int adis16400_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long info) { struct adis16400_state *st = iio_priv(indio_dev); + struct mutex *slock = &st->adis.state_lock; int ret, sps; switch (info) { case IIO_CHAN_INFO_CALIBBIAS: - mutex_lock(&indio_dev->mlock); ret = adis_write_reg_16(&st->adis, adis16400_addresses[chan->scan_index], val); - mutex_unlock(&indio_dev->mlock); return ret; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* * Need to cache values so we can update if the frequency * changes. */ - mutex_lock(&indio_dev->mlock); + mutex_lock(slock); st->filt_int = val; /* Work out update to current value */ sps = st->variant->get_freq(st); if (sps < 0) { - mutex_unlock(&indio_dev->mlock); + mutex_unlock(slock); return sps; } - ret = adis16400_set_filter(indio_dev, sps, + ret = __adis16400_set_filter(indio_dev, sps, val * 1000 + val2 / 1000); - mutex_unlock(&indio_dev->mlock); + mutex_unlock(slock); return ret; case IIO_CHAN_INFO_SAMP_FREQ: sps = val * 1000 + val2 / 1000; @@ -540,9 +540,9 @@ static int adis16400_write_raw(struct iio_dev *indio_dev, if (sps <= 0) return -EINVAL; - mutex_lock(&indio_dev->mlock); + mutex_lock(slock); ret = st->variant->set_freq(st, sps); - mutex_unlock(&indio_dev->mlock); + mutex_unlock(slock); return ret; default: return -EINVAL; @@ -553,6 +553,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long info) { struct adis16400_state *st = iio_priv(indio_dev); + struct mutex *slock = &st->adis.state_lock; int16_t val16; int ret; @@ -596,10 +597,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, return -EINVAL; } case IIO_CHAN_INFO_CALIBBIAS: - mutex_lock(&indio_dev->mlock); ret = adis_read_reg_16(&st->adis, adis16400_addresses[chan->scan_index], &val16); - mutex_unlock(&indio_dev->mlock); if (ret) return ret; val16 = sign_extend32(val16, 11); @@ -610,27 +609,27 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, *val = st->variant->temp_offset; return IIO_VAL_INT; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - mutex_lock(&indio_dev->mlock); + mutex_lock(slock); /* Need both the number of taps and the sampling frequency */ - ret = adis_read_reg_16(&st->adis, + ret = __adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16); if (ret) { - mutex_unlock(&indio_dev->mlock); + mutex_unlock(slock); return ret; } ret = st->variant->get_freq(st); - if (ret >= 0) { - ret /= adis16400_3db_divisors[val16 & 0x07]; - *val = ret / 1000; - *val2 = (ret % 1000) * 1000; - } - mutex_unlock(&indio_dev->mlock); + mutex_unlock(slock); if (ret) return ret; + ret /= adis16400_3db_divisors[val16 & 0x07]; + *val = ret / 1000; + *val2 = (ret % 1000) * 1000; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_SAMP_FREQ: + mutex_lock(slock); ret = st->variant->get_freq(st); + mutex_unlock(slock); if (ret) return ret; *val = ret / 1000; From 0aee99a1ea53de1aedcf96a4d52d6161ffba011a Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 22 Nov 2019 15:24:19 +0200 Subject: [PATCH 017/353] iio: gyro: adis16136: rework locks using ADIS library's state lock This replaces indio_dev's mlock with the state lock/mutex from the ADIS library. The __adis16136_get_freq() function has been prefixed to mark it as unlocked. The adis16136_{set,get}_filter() functions now hold the state lock for all the ops that they do. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/adis16136.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c index d637d52d051a..f10c4f173898 100644 --- a/drivers/iio/gyro/adis16136.c +++ b/drivers/iio/gyro/adis16136.c @@ -185,12 +185,12 @@ static int adis16136_set_freq(struct adis16136 *adis16136, unsigned int freq) return adis_write_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, t); } -static int adis16136_get_freq(struct adis16136 *adis16136, unsigned int *freq) +static int __adis16136_get_freq(struct adis16136 *adis16136, unsigned int *freq) { uint16_t t; int ret; - ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, &t); + ret = __adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, &t); if (ret) return ret; @@ -224,10 +224,13 @@ static ssize_t adis16136_read_frequency(struct device *dev, { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct adis16136 *adis16136 = iio_priv(indio_dev); + struct mutex *slock = &adis16136->adis.state_lock; unsigned int freq; int ret; - ret = adis16136_get_freq(adis16136, &freq); + mutex_lock(slock); + ret = __adis16136_get_freq(adis16136, &freq); + mutex_unlock(slock); if (ret) return ret; @@ -252,42 +255,50 @@ static const unsigned adis16136_3db_divisors[] = { static int adis16136_set_filter(struct iio_dev *indio_dev, int val) { struct adis16136 *adis16136 = iio_priv(indio_dev); + struct mutex *slock = &adis16136->adis.state_lock; unsigned int freq; int i, ret; - ret = adis16136_get_freq(adis16136, &freq); + mutex_lock(slock); + ret = __adis16136_get_freq(adis16136, &freq); if (ret) - return ret; + goto out_unlock; for (i = ARRAY_SIZE(adis16136_3db_divisors) - 1; i >= 1; i--) { if (freq / adis16136_3db_divisors[i] >= val) break; } - return adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i); + ret = __adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i); +out_unlock: + mutex_unlock(slock); + + return ret; } static int adis16136_get_filter(struct iio_dev *indio_dev, int *val) { struct adis16136 *adis16136 = iio_priv(indio_dev); + struct mutex *slock = &adis16136->adis.state_lock; unsigned int freq; uint16_t val16; int ret; - mutex_lock(&indio_dev->mlock); + mutex_lock(slock); - ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, &val16); + ret = __adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, + &val16); if (ret) goto err_unlock; - ret = adis16136_get_freq(adis16136, &freq); + ret = __adis16136_get_freq(adis16136, &freq); if (ret) goto err_unlock; *val = freq / adis16136_3db_divisors[val16 & 0x07]; err_unlock: - mutex_unlock(&indio_dev->mlock); + mutex_unlock(slock); return ret ? ret : IIO_VAL_INT; } From d693845da31c4d1093a8165d1ac4a73eac0f9373 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 22 Nov 2019 15:24:20 +0200 Subject: [PATCH 018/353] iio: imu: adis16480: use state lock for filter freq set It's the only operation that does 2 operations (a read & a write), so the unlocked functions can be used under a single state lock. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis16480.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index e943039c3f98..f73094e8d35d 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -555,6 +555,7 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, unsigned int freq) { struct adis16480 *st = iio_priv(indio_dev); + struct mutex *slock = &st->adis.state_lock; unsigned int enable_mask, offset, reg; unsigned int diff, best_diff; unsigned int i, best_freq; @@ -565,9 +566,11 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev, offset = ad16480_filter_data[chan->scan_index][1]; enable_mask = BIT(offset + 2); - ret = adis_read_reg_16(&st->adis, reg, &val); + mutex_lock(slock); + + ret = __adis_read_reg_16(&st->adis, reg, &val); if (ret) - return ret; + goto out_unlock; if (freq == 0) { val &= ~enable_mask; @@ -589,7 +592,11 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev, val |= enable_mask; } - return adis_write_reg_16(&st->adis, reg, val); + ret = __adis_write_reg_16(&st->adis, reg, val); +out_unlock: + mutex_unlock(slock); + + return ret; } static int adis16480_read_raw(struct iio_dev *indio_dev, From 160b37f49ec3b3adc6916f411ee3ceebea8dd13d Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 22 Nov 2019 15:24:21 +0200 Subject: [PATCH 019/353] iio: gyro: adis16260: replace mlock with ADIS lib's state_lock This change uses the ADIS library's state_lock to protect the state of the `max_speed_hz` change that is done during the set of the sampling frequency. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/adis16260.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c index 207a0ce13439..726a0aa321a8 100644 --- a/drivers/iio/gyro/adis16260.c +++ b/drivers/iio/gyro/adis16260.c @@ -293,7 +293,7 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, addr = adis16260_addresses[chan->scan_index][1]; return adis_write_reg_16(adis, addr, val); case IIO_CHAN_INFO_SAMP_FREQ: - mutex_lock(&indio_dev->mlock); + mutex_lock(&adis->state_lock); if (spi_get_device_id(adis->spi)->driver_data) t = 256 / val; else @@ -308,9 +308,9 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, adis->spi->max_speed_hz = ADIS16260_SPI_SLOW; else adis->spi->max_speed_hz = ADIS16260_SPI_FAST; - ret = adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t); + ret = __adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t); - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&adis->state_lock); return ret; } return -EINVAL; From 76aa41c17befa67b8727942d134eb65af501908b Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Wed, 20 Nov 2019 15:47:48 +0100 Subject: [PATCH 020/353] iio: max31856: add option for setting mains filter rejection frequency This sensor has an embedded notch filter for reducing interferences caused by the power mains. This filter can be tuned to reject either 50Hz or 60Hz (and harmonics). Currently the said setting is left alone (the sensor defaults to 60Hz). This patch introduces a IIO attribute that allows the user to set the said filter to the desired frequency. NOTE: this has been intentionally not tied to any DT property to allow the configuration of this setting from userspace, e.g. with a GUI or by reading a configuration file, or maybe reading a GPIO tied to a physical switch or accessing some device that can autodetect the line frequency. Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: Colin Ian King Cc: Patrick Havelange Cc: Matt Weber Cc: Matt Ranostay Cc: Chuhong Yuan Cc: Daniel Gomez Cc: linux-iio@vger.kernel.org Signed-off-by: Andrea Merello Reviewed-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/max31856.c | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/iio/temperature/max31856.c b/drivers/iio/temperature/max31856.c index 73ed550e3fc9..d97ba9ee1598 100644 --- a/drivers/iio/temperature/max31856.c +++ b/drivers/iio/temperature/max31856.c @@ -23,6 +23,7 @@ #define MAX31856_CR0_1SHOT BIT(6) #define MAX31856_CR0_OCFAULT BIT(4) #define MAX31856_CR0_OCFAULT_MASK GENMASK(5, 4) +#define MAX31856_CR0_FILTER_50HZ BIT(0) #define MAX31856_TC_TYPE_MASK GENMASK(3, 0) #define MAX31856_FAULT_OVUV BIT(1) #define MAX31856_FAULT_OPEN BIT(0) @@ -63,6 +64,7 @@ static const struct iio_chan_spec max31856_channels[] = { struct max31856_data { struct spi_device *spi; u32 thermocouple_type; + bool filter_50hz; }; static int max31856_read(struct max31856_data *data, u8 reg, @@ -123,6 +125,11 @@ static int max31856_init(struct max31856_data *data) reg_cr0_val &= ~MAX31856_CR0_1SHOT; reg_cr0_val |= MAX31856_CR0_AUTOCONVERT; + if (data->filter_50hz) + reg_cr0_val |= MAX31856_CR0_FILTER_50HZ; + else + reg_cr0_val &= ~MAX31856_CR0_FILTER_50HZ; + return max31856_write(data, MAX31856_CR0_REG, reg_cr0_val); } @@ -249,12 +256,54 @@ static ssize_t show_fault_oc(struct device *dev, return show_fault(dev, MAX31856_FAULT_OPEN, buf); } +static ssize_t show_filter(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct max31856_data *data = iio_priv(indio_dev); + + return sprintf(buf, "%d\n", data->filter_50hz ? 50 : 60); +} + +static ssize_t set_filter(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct max31856_data *data = iio_priv(indio_dev); + unsigned int freq; + int ret; + + ret = kstrtouint(buf, 10, &freq); + if (ret) + return ret; + + switch (freq) { + case 50: + data->filter_50hz = true; + break; + case 60: + data->filter_50hz = false; + break; + default: + return -EINVAL; + } + + max31856_init(data); + return len; +} + static IIO_DEVICE_ATTR(fault_ovuv, 0444, show_fault_ovuv, NULL, 0); static IIO_DEVICE_ATTR(fault_oc, 0444, show_fault_oc, NULL, 0); +static IIO_DEVICE_ATTR(in_temp_filter_notch_center_frequency, 0644, + show_filter, set_filter, 0); static struct attribute *max31856_attributes[] = { &iio_dev_attr_fault_ovuv.dev_attr.attr, &iio_dev_attr_fault_oc.dev_attr.attr, + &iio_dev_attr_in_temp_filter_notch_center_frequency.dev_attr.attr, NULL, }; @@ -280,6 +329,7 @@ static int max31856_probe(struct spi_device *spi) data = iio_priv(indio_dev); data->spi = spi; + data->filter_50hz = false; spi_set_drvdata(spi, indio_dev); From 3f6bba19071eac393a7f39755e235b286a7bb09a Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Wed, 20 Nov 2019 15:47:49 +0100 Subject: [PATCH 021/353] Documentation: ABI: document IIO in_temp_filter_notch_center_frequency file max31856 IIO driver introduced a new attribute "in_temp_filter_notch_center_frequency". This patch adds it to the list of documented ABI for sysfs-bus-iio Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: Colin Ian King Cc: Patrick Havelange Cc: Matt Weber Cc: Matt Ranostay Cc: Chuhong Yuan Cc: Daniel Gomez Cc: linux-iio@vger.kernel.org Signed-off-by: Andrea Merello Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index faaa2166d741..94f7eb675108 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1726,3 +1726,10 @@ Contact: linux-iio@vger.kernel.org Description: List of valid periods (in seconds) for which the light intensity must be above the threshold level before interrupt is asserted. + +What: /sys/bus/iio/devices/iio:deviceX/in_filter_notch_center_frequency +KernelVersion: 5.5 +Contact: linux-iio@vger.kernel.org +Description: + Center frequency in Hz for a notch filter. Used i.e. for line + noise suppression. From 57a4274ce168d4e63a7b5f4a8a776f7bdd5666a9 Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Wed, 20 Nov 2019 15:47:50 +0100 Subject: [PATCH 022/353] iio: max31856: add support for configuring the HW averaging This sensor can perform samples averaging in hardware, but currently the driver leaves this setting alone (default is no averaging). This patch binds this HW setting to the "oversampling_ratio" IIO attribute and allows the user to set the averaging as desired (the HW supports averaging of 2, 5, 8 or 16 samples; in-between values are rounded up). Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: Colin Ian King Cc: Patrick Havelange Cc: Matt Weber Cc: Matt Ranostay Cc: Chuhong Yuan Cc: Daniel Gomez Cc: linux-iio@vger.kernel.org Signed-off-by: Andrea Merello Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/max31856.c | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/iio/temperature/max31856.c b/drivers/iio/temperature/max31856.c index d97ba9ee1598..8457ca9ae326 100644 --- a/drivers/iio/temperature/max31856.c +++ b/drivers/iio/temperature/max31856.c @@ -12,6 +12,7 @@ #include #include #include +#include #include /* * The MSB of the register value determines whether the following byte will @@ -24,6 +25,8 @@ #define MAX31856_CR0_OCFAULT BIT(4) #define MAX31856_CR0_OCFAULT_MASK GENMASK(5, 4) #define MAX31856_CR0_FILTER_50HZ BIT(0) +#define MAX31856_AVERAGING_MASK GENMASK(6, 4) +#define MAX31856_AVERAGING_SHIFT 4 #define MAX31856_TC_TYPE_MASK GENMASK(3, 0) #define MAX31856_FAULT_OVUV BIT(1) #define MAX31856_FAULT_OPEN BIT(0) @@ -51,6 +54,8 @@ static const struct iio_chan_spec max31856_channels[] = { .type = IIO_TEMP, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type = + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) }, { /* Cold Junction Temperature */ .type = IIO_TEMP, @@ -58,6 +63,8 @@ static const struct iio_chan_spec max31856_channels[] = { .modified = 1, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type = + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) }, }; @@ -65,6 +72,7 @@ struct max31856_data { struct spi_device *spi; u32 thermocouple_type; bool filter_50hz; + int averaging; }; static int max31856_read(struct max31856_data *data, u8 reg, @@ -109,6 +117,10 @@ static int max31856_init(struct max31856_data *data) reg_cr1_val &= ~MAX31856_TC_TYPE_MASK; reg_cr1_val |= data->thermocouple_type; + + reg_cr1_val &= ~MAX31856_AVERAGING_MASK; + reg_cr1_val |= data->averaging << MAX31856_AVERAGING_SHIFT; + ret = max31856_write(data, MAX31856_CR1_REG, reg_cr1_val); if (ret) return ret; @@ -217,6 +229,9 @@ static int max31856_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_MICRO; } break; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *val = 1 << data->averaging; + return IIO_VAL_INT; default: ret = -EINVAL; break; @@ -225,6 +240,33 @@ static int max31856_read_raw(struct iio_dev *indio_dev, return ret; } +static int max31856_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct max31856_data *data = iio_priv(indio_dev); + int msb; + + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + if (val > 16 || val < 1) + return -EINVAL; + msb = fls(val) - 1; + /* Round up to next 2pow if needed */ + if (BIT(msb) < val) + msb++; + + data->averaging = msb; + max31856_init(data); + break; + + default: + return -EINVAL; + } + + return 0; +} + static ssize_t show_fault(struct device *dev, u8 faultbit, char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); @@ -313,6 +355,7 @@ static const struct attribute_group max31856_group = { static const struct iio_info max31856_info = { .read_raw = max31856_read_raw, + .write_raw = max31856_write_raw, .attrs = &max31856_group, }; From 8cb3403633146afe1ba81f79224679f5df2940d4 Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Wed, 20 Nov 2019 15:47:51 +0100 Subject: [PATCH 023/353] iio: core: add char type for sysfs attributes This patch introduces IIO_VAL_CHAR type for standard IIO attributes to allow for attributes that needs to be represented by character rather than a number. This is preparatory for introducing a new attribute whose purpose is to describe thermocouple type, that can be i.e. "J", "K", etc.. The char-type value is stored in the first "value" integer that is passed to the .[read/write]_raw() callbacks. Note that in order to make it possible for the IIO core to correctly parse this type (actually, to avoid integer parsing), it became mandatory for any driver that wish to use IIO_VAL_CHAR on a writable attribute to implement .write_raw_get_fmt(). Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: Colin Ian King Cc: Patrick Havelange Cc: Matt Weber Cc: Matt Ranostay Cc: Chuhong Yuan Cc: Daniel Gomez Cc: linux-iio@vger.kernel.org Signed-off-by: Andrea Merello Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-core.c | 22 ++++++++++++++++++---- include/linux/iio/types.h | 1 + 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index f72c2dc5f703..958b5c48a86f 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -596,6 +596,8 @@ static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type, } return l; } + case IIO_VAL_CHAR: + return snprintf(buf, len, "%c", (char)vals[0]); default: return 0; } @@ -837,7 +839,8 @@ static ssize_t iio_write_channel_info(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret, fract_mult = 100000; - int integer, fract; + int integer, fract = 0; + bool is_char = false; /* Assumes decimal - precision based on number of digits */ if (!indio_dev->info->write_raw) @@ -855,13 +858,24 @@ static ssize_t iio_write_channel_info(struct device *dev, case IIO_VAL_INT_PLUS_NANO: fract_mult = 100000000; break; + case IIO_VAL_CHAR: + is_char = true; + break; default: return -EINVAL; } - ret = iio_str_to_fixpoint(buf, fract_mult, &integer, &fract); - if (ret) - return ret; + if (is_char) { + char ch; + + if (sscanf(buf, "%c", &ch) != 1) + return -EINVAL; + integer = ch; + } else { + ret = iio_str_to_fixpoint(buf, fract_mult, &integer, &fract); + if (ret) + return ret; + } ret = indio_dev->info->write_raw(indio_dev, this_attr->c, integer, fract, this_attr->address); diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index fa824e160f35..8e0026da38c9 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -25,6 +25,7 @@ enum iio_event_info { #define IIO_VAL_INT_MULTIPLE 5 #define IIO_VAL_FRACTIONAL 10 #define IIO_VAL_FRACTIONAL_LOG2 11 +#define IIO_VAL_CHAR 12 enum iio_available_type { IIO_AVAIL_LIST, From ddfb97d8f06c98fa5d80bbb6a997155a838161e9 Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Wed, 20 Nov 2019 15:47:52 +0100 Subject: [PATCH 024/353] iio: core: add thermocouple_type standard attribute We have a couple of thermocouple IIO drivers, supporting several chips. Some of them support only one specific thermocouple type (e.g. "K", "J"), one of them can be configured to work with several different thermocouple types. In certain applications thermocouples could be externally connected to the chip by the user. This patch introduces a new IIO standard attribute to report the supported thermocouple type and, where applicable, to allow it to be dynamically set using sysfs. Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: Colin Ian King Cc: Patrick Havelange Cc: Matt Weber Cc: Matt Ranostay Cc: Chuhong Yuan Cc: Daniel Gomez Cc: linux-iio@vger.kernel.org Signed-off-by: Andrea Merello Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-core.c | 1 + include/linux/iio/types.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 958b5c48a86f..fa2c3b321bfd 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -161,6 +161,7 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_DEBOUNCE_TIME] = "debounce_time", [IIO_CHAN_INFO_CALIBEMISSIVITY] = "calibemissivity", [IIO_CHAN_INFO_OVERSAMPLING_RATIO] = "oversampling_ratio", + [IIO_CHAN_INFO_THERMOCOUPLE_TYPE] = "thermocouple_type", }; /** diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 8e0026da38c9..e6fd3645963c 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -58,6 +58,7 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_DEBOUNCE_TIME, IIO_CHAN_INFO_CALIBEMISSIVITY, IIO_CHAN_INFO_OVERSAMPLING_RATIO, + IIO_CHAN_INFO_THERMOCOUPLE_TYPE, }; #endif /* _IIO_TYPES_H_ */ From 83b9af6f283e95e9a9c2b5dc684d054278ac4728 Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Wed, 20 Nov 2019 15:47:53 +0100 Subject: [PATCH 025/353] Documentation: ABI: document IIO thermocouple_type file IIO core layer gained a new sysfs standard attribute "thermocouple_type". This patch adds it to the list of documented ABI for sysfs-bus-iio Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: Colin Ian King Cc: Patrick Havelange Cc: Matt Weber Cc: Matt Ranostay Cc: Chuhong Yuan Cc: Daniel Gomez Cc: linux-iio@vger.kernel.org Signed-off-by: Andrea Merello Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 94f7eb675108..d3e53a6d8331 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1733,3 +1733,9 @@ Contact: linux-iio@vger.kernel.org Description: Center frequency in Hz for a notch filter. Used i.e. for line noise suppression. + +What: /sys/bus/iio/devices/iio:deviceX/in_temp_thermocouple_type +KernelVersion: 5.5 +Contact: linux-iio@vger.kernel.org +Description: + One of the following thermocouple types: B, E, J, K, N, R, S, T. From ea4103070f03f789f305bdd1803d5d4c42f0b3b9 Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Wed, 20 Nov 2019 15:47:54 +0100 Subject: [PATCH 026/353] iio: max31856: add support for runtime-configuring the thermocouple type The sensor support various thermocouple types (e.g. J, K, N, ...). The driver allows to configure this parameter using a DT property. This is useful when i.e. the thermocouple is physically tied to the sensor and it is usually not removed, or when it is at least known in advance which sensor will be connected to the circuit. However, if the user can randomly connect any kind of thermocouples (i.e. the device exposes a connector, and the user is free to connect its own sensors), it would be more appropriate to provide a mechanism to dynamically switch from one thermocouple type to another. This can be i.e. handled in userspace by a GUI, a configuration file or a program that detects the thermocouple type by reading a GPIO, or a eeprom on the probe, or whatever. This patch adds a IIO attribute that can be used to override, at run-time, the DT-provided setting (which serves as default). Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: Colin Ian King Cc: Patrick Havelange Cc: Matt Weber Cc: Matt Ranostay Cc: Chuhong Yuan Cc: Daniel Gomez Cc: linux-iio@vger.kernel.org Signed-off-by: Andrea Merello Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/max31856.c | 41 +++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/iio/temperature/max31856.c b/drivers/iio/temperature/max31856.c index 8457ca9ae326..b4cb21ab2e85 100644 --- a/drivers/iio/temperature/max31856.c +++ b/drivers/iio/temperature/max31856.c @@ -6,6 +6,7 @@ * Copyright (C) 2018-2019 Rockwell Collins */ +#include #include #include #include @@ -53,7 +54,8 @@ static const struct iio_chan_spec max31856_channels[] = { { /* Thermocouple Temperature */ .type = IIO_TEMP, .info_mask_separate = - BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_THERMOCOUPLE_TYPE), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) }, @@ -75,6 +77,10 @@ struct max31856_data { int averaging; }; +static const char max31856_tc_types[] = { + 'B', 'E', 'J', 'K', 'N', 'R', 'S', 'T' +}; + static int max31856_read(struct max31856_data *data, u8 reg, u8 val[], unsigned int read_size) { @@ -232,6 +238,9 @@ static int max31856_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_OVERSAMPLING_RATIO: *val = 1 << data->averaging; return IIO_VAL_INT; + case IIO_CHAN_INFO_THERMOCOUPLE_TYPE: + *val = max31856_tc_types[data->thermocouple_type]; + return IIO_VAL_CHAR; default: ret = -EINVAL; break; @@ -240,6 +249,18 @@ static int max31856_read_raw(struct iio_dev *indio_dev, return ret; } +static int max31856_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_THERMOCOUPLE_TYPE: + return IIO_VAL_CHAR; + default: + return IIO_VAL_INT; + } +} + static int max31856_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) @@ -259,7 +280,24 @@ static int max31856_write_raw(struct iio_dev *indio_dev, data->averaging = msb; max31856_init(data); break; + case IIO_CHAN_INFO_THERMOCOUPLE_TYPE: + { + int tc_type = -1; + int i; + for (i = 0; i < ARRAY_SIZE(max31856_tc_types); i++) { + if (max31856_tc_types[i] == toupper(val)) { + tc_type = i; + break; + } + } + if (tc_type < 0) + return -EINVAL; + + data->thermocouple_type = tc_type; + max31856_init(data); + break; + } default: return -EINVAL; } @@ -356,6 +394,7 @@ static const struct attribute_group max31856_group = { static const struct iio_info max31856_info = { .read_raw = max31856_read_raw, .write_raw = max31856_write_raw, + .write_raw_get_fmt = max31856_write_raw_get_fmt, .attrs = &max31856_group, }; From d7f6a749f30bc2296e0d92553aa9f4daad7bcf1f Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Wed, 20 Nov 2019 15:47:55 +0100 Subject: [PATCH 027/353] iio: maxim_thermocouple: add thermocouple_type sysfs attribute We added a sysfs ABI for getting/setting the type of a thermocouple. This driver supports chips that support specific fixed thermocouple types; we cannot set it, but still we can add this sysfs attribute in RO mode to read-back the thermocouple type. This driver supports actually several chips: - max6675 - max31855[k/j/n/s/t/e/r]asa family Max6675 supports only K-type thermocouples, so we can just report that. Each chip in max31855 family supports just one specific thermocouple type (in the obvious way: i.e. max31855jasa supports J-type). This driver did accept a generic SPI ID and OF compatible "max31855" which does not give any clue about which chip is really involved (and unfortunately it seems we have no way to detect it). This patch introduces a new set of, more specific, SPI IDs and OF compatible strings to better match the chip type. The old, generic, "max31855" binding is kept for compatibility reasons, but this patch aims to deprecate it, so, should we hit it, a warning is spit. In such case the reported thermocouple type in sysfs is '?', because we have no way to know. Regarding the implementation: the thermocouple type information is stored in the driver private data and I've kept only two maxim_thermocouple_chip types in order to avoid a lot of duplications (seven chip types with just a different thermocouple type). RFT because I have no real HW to test this. Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: Colin Ian King Cc: Patrick Havelange Cc: Matt Weber Cc: Matt Ranostay Cc: Chuhong Yuan Cc: Daniel Gomez Cc: linux-iio@vger.kernel.org Cc: Rob Herring Cc: Mark Rutland Cc: devicetree@vger.kernel.org Signed-off-by: Andrea Merello Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/maxim_thermocouple.c | 44 ++++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c index d1360605209c..8d21116c7a22 100644 --- a/drivers/iio/temperature/maxim_thermocouple.c +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -24,13 +25,25 @@ enum { MAX6675, MAX31855, + MAX31855K, + MAX31855J, + MAX31855N, + MAX31855S, + MAX31855T, + MAX31855E, + MAX31855R, +}; + +static const char maxim_tc_types[] = { + 'K', '?', 'K', 'J', 'N', 'S', 'T', 'E', 'R' }; static const struct iio_chan_spec max6675_channels[] = { { /* thermocouple temperature */ .type = IIO_TEMP, .info_mask_separate = - BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_THERMOCOUPLE_TYPE), .scan_index = 0, .scan_type = { .sign = 's', @@ -48,7 +61,8 @@ static const struct iio_chan_spec max31855_channels[] = { .type = IIO_TEMP, .address = 2, .info_mask_separate = - BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_THERMOCOUPLE_TYPE), .scan_index = 0, .scan_type = { .sign = 's', @@ -110,6 +124,7 @@ struct maxim_thermocouple_data { const struct maxim_thermocouple_chip *chip; u8 buffer[16] ____cacheline_aligned; + char tc_type; }; static int maxim_thermocouple_read(struct maxim_thermocouple_data *data, @@ -196,6 +211,10 @@ static int maxim_thermocouple_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; } break; + case IIO_CHAN_INFO_THERMOCOUPLE_TYPE: + *val = data->tc_type; + ret = IIO_VAL_CHAR; + break; } return ret; @@ -210,8 +229,9 @@ static int maxim_thermocouple_probe(struct spi_device *spi) const struct spi_device_id *id = spi_get_device_id(spi); struct iio_dev *indio_dev; struct maxim_thermocouple_data *data; + const int chip_type = (id->driver_data == MAX6675) ? MAX6675 : MAX31855; const struct maxim_thermocouple_chip *chip = - &maxim_thermocouple_chips[id->driver_data]; + &maxim_thermocouple_chips[chip_type]; int ret; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data)); @@ -229,6 +249,7 @@ static int maxim_thermocouple_probe(struct spi_device *spi) data = iio_priv(indio_dev); data->spi = spi; data->chip = chip; + data->tc_type = maxim_tc_types[id->driver_data]; ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, @@ -236,12 +257,22 @@ static int maxim_thermocouple_probe(struct spi_device *spi) if (ret) return ret; + if (id->driver_data == MAX31855) + dev_warn(&spi->dev, "generic max31855 ID is deprecated\nplease use more specific part type"); + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct spi_device_id maxim_thermocouple_id[] = { {"max6675", MAX6675}, {"max31855", MAX31855}, + {"max31855k", MAX31855K}, + {"max31855j", MAX31855J}, + {"max31855n", MAX31855N}, + {"max31855s", MAX31855S}, + {"max31855t", MAX31855T}, + {"max31855e", MAX31855E}, + {"max31855r", MAX31855R}, {}, }; MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id); @@ -249,6 +280,13 @@ MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id); static const struct of_device_id maxim_thermocouple_of_match[] = { { .compatible = "maxim,max6675" }, { .compatible = "maxim,max31855" }, + { .compatible = "maxim,max31855k" }, + { .compatible = "maxim,max31855j" }, + { .compatible = "maxim,max31855n" }, + { .compatible = "maxim,max31855s" }, + { .compatible = "maxim,max31855t" }, + { .compatible = "maxim,max31855e" }, + { .compatible = "maxim,max31855r" }, { }, }; MODULE_DEVICE_TABLE(of, maxim_thermocouple_of_match); From 3922f930de9d83fab3dcdc432ac046d79583e430 Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Wed, 20 Nov 2019 15:47:56 +0100 Subject: [PATCH 028/353] dt-bindings: iio: maxim_thermocouple: document new 'compatible' strings Now the maxim_thermocouple has new, more specific, 'compatible' strings for better distinguish the various supported chips. This patch updates the DT bindings documentation accordingly Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: Colin Ian King Cc: Patrick Havelange Cc: Matt Weber Cc: Matt Ranostay Cc: Chuhong Yuan Cc: Daniel Gomez Cc: linux-iio@vger.kernel.org Cc: Rob Herring Cc: Mark Rutland Cc: devicetree@vger.kernel.org Signed-off-by: Andrea Merello Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/temperature/maxim_thermocouple.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt b/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt index 28bc5c4d965b..bb85cd0e039c 100644 --- a/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt +++ b/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt @@ -5,7 +5,10 @@ Maxim thermocouple support Required properties: - - compatible: must be "maxim,max31855" or "maxim,max6675" + - compatible: must be "maxim,max6675" or one of the following: + "maxim,max31855k", "maxim,max31855j", "maxim,max31855n", + "maxim,max31855s", "maxim,max31855t", "maxim,max31855e", + "maxim,max31855r"; the generic "max,max31855" is deprecated. - reg: SPI chip select number for the device - spi-max-frequency: must be 4300000 - spi-cpha: must be defined for max6675 to enable SPI mode 1 @@ -15,7 +18,7 @@ Required properties: Example: max31855@0 { - compatible = "maxim,max31855"; + compatible = "maxim,max31855k"; reg = <0>; spi-max-frequency = <4300000>; }; From a8b26c2ddc83fab7f582405c468df2cbb9b5348a Mon Sep 17 00:00:00 2001 From: Alexandru Tachici Date: Mon, 18 Nov 2019 12:58:07 +0200 Subject: [PATCH 029/353] iio: dac: ad7303: use regulator get optional to check for ext supply Previously, the code was using the of_read_property_bool() to check if an external regulator was provided. However, this is redundant, as it's more simple/direct to just ask the regulator is provided, via a `devm_regulator_get_optional()` call. Signed-off-by: Alexandru Tachici Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad7303.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c index 14bbac6bee98..15af8a1cce3e 100644 --- a/drivers/iio/dac/ad7303.c +++ b/drivers/iio/dac/ad7303.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -202,7 +201,6 @@ static int ad7303_probe(struct spi_device *spi) const struct spi_device_id *id = spi_get_device_id(spi); struct iio_dev *indio_dev; struct ad7303_state *st; - bool ext_ref; int ret; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); @@ -224,24 +222,15 @@ static int ad7303_probe(struct spi_device *spi) if (ret) return ret; - if (spi->dev.of_node) { - ext_ref = of_property_read_bool(spi->dev.of_node, - "REF-supply"); - } else { - struct ad7303_platform_data *pdata = spi->dev.platform_data; - if (pdata && pdata->use_external_ref) - ext_ref = true; - else - ext_ref = false; + st->vref_reg = devm_regulator_get_optional(&spi->dev, "REF"); + if (IS_ERR(st->vref_reg)) { + ret = PTR_ERR(st->vref_reg); + if (ret != -ENODEV) + goto err_disable_vdd_reg; + st->vref_reg = NULL; } - if (ext_ref) { - st->vref_reg = devm_regulator_get(&spi->dev, "REF"); - if (IS_ERR(st->vref_reg)) { - ret = PTR_ERR(st->vref_reg); - goto err_disable_vdd_reg; - } - + if (st->vref_reg) { ret = regulator_enable(st->vref_reg); if (ret) goto err_disable_vdd_reg; From 3e9769624bd6c86744f72ab43b0a098f23478454 Mon Sep 17 00:00:00 2001 From: Andreas Klinger Date: Mon, 18 Nov 2019 08:35:55 +0100 Subject: [PATCH 030/353] dt-bindings: add vendor prefix parallax Add new vendor prefix parallax for newly created ping iio sensors. Signed-off-by: Andreas Klinger Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 967e78c5ec0a..d3f9690e1e4b 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -713,6 +713,8 @@ patternProperties: description: Panasonic Corporation "^parade,.*": description: Parade Technologies Inc. + "^parallax,.*": + description: Parallax Inc. "^pda,.*": description: Precision Design Associates, Inc. "^pericom,.*": From b7f35e7dc8aa880751711a4f1171f7ee6b9f26c7 Mon Sep 17 00:00:00 2001 From: Andreas Klinger Date: Mon, 18 Nov 2019 08:36:12 +0100 Subject: [PATCH 031/353] dt-bindings: add parallax ping sensors Add dt-bindings for parallax PING))) and LaserPING iio sensors, which are used for measuring distances. Signed-off-by: Andreas Klinger Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/proximity/parallax-ping.yaml | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/proximity/parallax-ping.yaml diff --git a/Documentation/devicetree/bindings/iio/proximity/parallax-ping.yaml b/Documentation/devicetree/bindings/iio/proximity/parallax-ping.yaml new file mode 100644 index 000000000000..a079c9921af6 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/proximity/parallax-ping.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/proximity/parallax-ping.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Parallax PING))) and LaserPING range finder + +maintainers: + - Andreas Klinger + +description: | + Bit-banging driver using one GPIO: + - ping-gpios is raised by the driver to start measurement + - direction of ping-gpio is then switched into input with an interrupt + for receiving distance value as PWM signal + + Specifications about the devices can be found at: + http://parallax.com/sites/default/files/downloads/28041-LaserPING-2m-Rangefinder-Guide.pdf + http://parallax.com/sites/default/files/downloads/28015-PING-Documentation-v1.6.pdf + +properties: + compatible: + enum: + - parallax,ping + - parallax,laserping + + ping-gpios: + description: + Definition of the GPIO for the triggering and echo (output and input) + This GPIO is set for about 5 us by the driver to tell the device it + should initiate the measurement cycle. Afterwards the GPIO is switched + to input direction with an interrupt. The device sets it and the + length of the input signal corresponds to the measured distance. + It needs to be an GPIO which is able to deliver an interrupt because + the time between two interrupts is measured in the driver. + See Documentation/devicetree/bindings/gpio/gpio.txt for information + on how to specify a consumer gpio. + maxItems: 1 + +required: + - compatible + - ping-gpios + +examples: + - | + #include + proximity { + compatible = "parallax,laserping"; + ping-gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>; + }; From 0f8b1293ad6fa8b3125d42dc8acad8b97ef4972a Mon Sep 17 00:00:00 2001 From: Andreas Klinger Date: Mon, 18 Nov 2019 08:36:50 +0100 Subject: [PATCH 032/353] MAINTAINERS: add maintainer for ping iio sensors Add a maintainer for the new parallax PING))) and LaserPING IIO sensors Signed-off-by: Andreas Klinger Signed-off-by: Jonathan Cameron --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3ef731fc753b..01212ae1a2d4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12293,6 +12293,13 @@ L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/panasonic-laptop.c +PARALLAX PING IIO SENSOR DRIVER +M: Andreas Klinger +L: linux-iio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/iio/proximity/parallax-ping.yaml +F: drivers/iio/proximity/ping.c + PARALLEL LCD/KEYPAD PANEL DRIVER M: Willy Tarreau M: Ksenija Stanojevic From 7dd1cfc1398a79430e998a1f2894aa34c7fb749b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 21 Nov 2019 04:19:19 +0100 Subject: [PATCH 033/353] iio: Fix Kconfig indentation Adjust indentation from spaces to tab (+optional two spaces) as in coding style with command like: $ sed -e 's/^ /\t/' -i */Kconfig Signed-off-by: Krzysztof Kozlowski Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/Kconfig | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index 95e6f96d4529..7eaf77707b0b 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig @@ -75,26 +75,26 @@ config BMG160_SPI select REGMAP_SPI config FXAS21002C - tristate "NXP FXAS21002C Gyro Sensor" - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - select FXAS21002C_I2C if (I2C) - select FXAS21002C_SPI if (SPI) - depends on (I2C || SPI_MASTER) - help - Say yes here to build support for NXP FXAS21002C Tri-axis Gyro - Sensor driver connected via I2C or SPI. + tristate "NXP FXAS21002C Gyro Sensor" + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + select FXAS21002C_I2C if (I2C) + select FXAS21002C_SPI if (SPI) + depends on (I2C || SPI_MASTER) + help + Say yes here to build support for NXP FXAS21002C Tri-axis Gyro + Sensor driver connected via I2C or SPI. - This driver can also be built as a module. If so, the module - will be called fxas21002c_i2c or fxas21002c_spi. + This driver can also be built as a module. If so, the module + will be called fxas21002c_i2c or fxas21002c_spi. config FXAS21002C_I2C - tristate - select REGMAP_I2C + tristate + select REGMAP_I2C config FXAS21002C_SPI - tristate - select REGMAP_SPI + tristate + select REGMAP_SPI config HID_SENSOR_GYRO_3D depends on HID_SENSOR_HUB From f3bcd06f574a0751ee40ec25b9aad6968877ae5f Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Thu, 21 Nov 2019 12:05:17 +0100 Subject: [PATCH 034/353] iio: trigger: stm32-timer: remove unnecessary update event There is no need to explicitly generate update event to update timer master mode. Signed-off-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/trigger/stm32-timer-trigger.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index a5dfe65cd9b9..2e0d32aa8436 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -297,9 +297,6 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev, strlen(master_mode_table[i]))) { regmap_update_bits(priv->regmap, TIM_CR2, mask, i << shift); - /* Make sure that registers are updated */ - regmap_update_bits(priv->regmap, TIM_EGR, - TIM_EGR_UG, TIM_EGR_UG); return len; } } From 7bb501f49ddb96365ef8d4fe882e5ceaa36215e4 Mon Sep 17 00:00:00 2001 From: Andreas Klinger Date: Mon, 25 Nov 2019 09:05:02 +0100 Subject: [PATCH 035/353] iio: ping: add parallax ping sensors Add support for parallax ping and laser ping sensors with just one pin for trigger and echo signal. This driver is based on srf04. In contrast to it it's necessary to change direction of the pin and to request the irq just for the period when the echo is rising and falling. Because this adds a lot of cases there is this individual driver for handling this type of sensors. Add a new configuration variable CONFIG_PING to Kconfig and Makefile. Julia reported an issue with failing to unlock a mutex in some error paths. Signed-off-by: Andreas Klinger Reported-by: kbuild test robot Reported-by: Julia Lawall Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/Kconfig | 15 ++ drivers/iio/proximity/Makefile | 1 + drivers/iio/proximity/ping.c | 335 +++++++++++++++++++++++++++++++++ 3 files changed, 351 insertions(+) create mode 100644 drivers/iio/proximity/ping.c diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index d53601447da4..37606d400805 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig @@ -58,6 +58,21 @@ config MB1232 To compile this driver as a module, choose M here: the module will be called mb1232. +config PING + tristate "Parallax GPIO bitbanged ranger sensors" + depends on GPIOLIB + help + Say Y here to build a driver for GPIO bitbanged ranger sensors + with just one GPIO for the trigger and echo. This driver can be + used to measure the distance of objects. + + Actually supported are: + - Parallax PING))) (ultrasonic) + - Parallax LaserPING (time-of-flight) + + To compile this driver as a module, choose M here: the + module will be called ping. + config RFD77402 tristate "RFD77402 ToF sensor" depends on I2C diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile index 0bb5f9de13d6..c591b019304e 100644 --- a/drivers/iio/proximity/Makefile +++ b/drivers/iio/proximity/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_AS3935) += as3935.o obj-$(CONFIG_ISL29501) += isl29501.o obj-$(CONFIG_LIDAR_LITE_V2) += pulsedlight-lidar-lite-v2.o obj-$(CONFIG_MB1232) += mb1232.o +obj-$(CONFIG_PING) += ping.o obj-$(CONFIG_RFD77402) += rfd77402.o obj-$(CONFIG_SRF04) += srf04.o obj-$(CONFIG_SRF08) += srf08.o diff --git a/drivers/iio/proximity/ping.c b/drivers/iio/proximity/ping.c new file mode 100644 index 000000000000..34aff108dff5 --- /dev/null +++ b/drivers/iio/proximity/ping.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * PING: ultrasonic sensor for distance measuring by using only one GPIOs + * + * Copyright (c) 2019 Andreas Klinger + * + * For details about the devices see: + * http://parallax.com/sites/default/files/downloads/28041-LaserPING-2m-Rangefinder-Guide.pdf + * http://parallax.com/sites/default/files/downloads/28015-PING-Documentation-v1.6.pdf + * + * the measurement cycle as timing diagram looks like: + * + * GPIO ___ ________________________ + * ping: __/ \____________/ \________________ + * ^ ^ ^ ^ + * |<->| interrupt interrupt + * udelay(5) (ts_rising) (ts_falling) + * |<---------------------->| + * . pulse time measured . + * . --> one round trip of ultra sonic waves + * ultra . . + * sonic _ _ _. . + * burst: _________/ \_/ \_/ \_________________________________________ + * . + * ultra . + * sonic _ _ _. + * echo: __________________________________/ \_/ \_/ \________________ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ping_cfg { + unsigned long trigger_pulse_us; /* length of trigger pulse */ + int laserping_error; /* support error code in */ + /* pulse width of laser */ + /* ping sensors */ + s64 timeout_ns; /* timeout in ns */ +}; + +struct ping_data { + struct device *dev; + struct gpio_desc *gpiod_ping; + struct mutex lock; + int irqnr; + ktime_t ts_rising; + ktime_t ts_falling; + struct completion rising; + struct completion falling; + const struct ping_cfg *cfg; +}; + +static const struct ping_cfg pa_ping_cfg = { + .trigger_pulse_us = 5, + .laserping_error = 0, + .timeout_ns = 18500000, /* 3 meters */ +}; + +static const struct ping_cfg pa_laser_ping_cfg = { + .trigger_pulse_us = 5, + .laserping_error = 1, + .timeout_ns = 15500000, /* 2 meters plus error codes */ +}; + +static irqreturn_t ping_handle_irq(int irq, void *dev_id) +{ + struct iio_dev *indio_dev = dev_id; + struct ping_data *data = iio_priv(indio_dev); + ktime_t now = ktime_get(); + + if (gpiod_get_value(data->gpiod_ping)) { + data->ts_rising = now; + complete(&data->rising); + } else { + data->ts_falling = now; + complete(&data->falling); + } + + return IRQ_HANDLED; +} + +static int ping_read(struct ping_data *data) +{ + int ret; + ktime_t ktime_dt; + s64 dt_ns; + u32 time_ns, distance_mm; + struct platform_device *pdev = to_platform_device(data->dev); + struct iio_dev *indio_dev = iio_priv_to_dev(data); + + /* + * just one read-echo-cycle can take place at a time + * ==> lock against concurrent reading calls + */ + mutex_lock(&data->lock); + + reinit_completion(&data->rising); + reinit_completion(&data->falling); + + gpiod_set_value(data->gpiod_ping, 1); + udelay(data->cfg->trigger_pulse_us); + gpiod_set_value(data->gpiod_ping, 0); + + ret = gpiod_direction_input(data->gpiod_ping); + if (ret < 0) { + mutex_unlock(&data->lock); + return ret; + } + + data->irqnr = gpiod_to_irq(data->gpiod_ping); + if (data->irqnr < 0) { + dev_err(data->dev, "gpiod_to_irq: %d\n", data->irqnr); + mutex_unlock(&data->lock); + return data->irqnr; + } + + ret = request_irq(data->irqnr, ping_handle_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + pdev->name, indio_dev); + if (ret < 0) { + dev_err(data->dev, "request_irq: %d\n", ret); + mutex_unlock(&data->lock); + return ret; + } + + /* it should not take more than 20 ms until echo is rising */ + ret = wait_for_completion_killable_timeout(&data->rising, HZ/50); + if (ret < 0) + goto err_reset_direction; + else if (ret == 0) { + ret = -ETIMEDOUT; + goto err_reset_direction; + } + + /* it cannot take more than 50 ms until echo is falling */ + ret = wait_for_completion_killable_timeout(&data->falling, HZ/20); + if (ret < 0) + goto err_reset_direction; + else if (ret == 0) { + ret = -ETIMEDOUT; + goto err_reset_direction; + } + + ktime_dt = ktime_sub(data->ts_falling, data->ts_rising); + + free_irq(data->irqnr, indio_dev); + + ret = gpiod_direction_output(data->gpiod_ping, GPIOD_OUT_LOW); + if (ret < 0) { + mutex_unlock(&data->lock); + return ret; + } + + mutex_unlock(&data->lock); + + dt_ns = ktime_to_ns(ktime_dt); + if (dt_ns > data->cfg->timeout_ns) { + dev_dbg(data->dev, "distance out of range: dt=%lldns\n", + dt_ns); + return -EIO; + } + + time_ns = dt_ns; + + /* + * read error code of laser ping sensor and give users chance to + * figure out error by using dynamic debuggging + */ + if (data->cfg->laserping_error) { + if ((time_ns > 12500000) && (time_ns <= 13500000)) { + dev_dbg(data->dev, "target too close or to far\n"); + return -EIO; + } + if ((time_ns > 13500000) && (time_ns <= 14500000)) { + dev_dbg(data->dev, "internal sensor error\n"); + return -EIO; + } + if ((time_ns > 14500000) && (time_ns <= 15500000)) { + dev_dbg(data->dev, "internal sensor timeout\n"); + return -EIO; + } + } + + /* + * the speed as function of the temperature is approximately: + * + * speed = 331,5 + 0,6 * Temp + * with Temp in °C + * and speed in m/s + * + * use 343,5 m/s as ultrasonic speed at 20 °C here in absence of the + * temperature + * + * therefore: + * time 343,5 time * 232 + * distance = ------ * ------- = ------------ + * 10^6 2 1350800 + * with time in ns + * and distance in mm (one way) + * + * because we limit to 3 meters the multiplication with 232 just + * fits into 32 bit + */ + distance_mm = time_ns * 232 / 1350800; + + return distance_mm; + +err_reset_direction: + free_irq(data->irqnr, indio_dev); + mutex_unlock(&data->lock); + + if (gpiod_direction_output(data->gpiod_ping, GPIOD_OUT_LOW)) + dev_dbg(data->dev, "error in gpiod_direction_output\n"); + return ret; +} + +static int ping_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *channel, int *val, + int *val2, long info) +{ + struct ping_data *data = iio_priv(indio_dev); + int ret; + + if (channel->type != IIO_DISTANCE) + return -EINVAL; + + switch (info) { + case IIO_CHAN_INFO_RAW: + ret = ping_read(data); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + /* + * maximum resolution in datasheet is 1 mm + * 1 LSB is 1 mm + */ + *val = 0; + *val2 = 1000; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static const struct iio_info ping_iio_info = { + .read_raw = ping_read_raw, +}; + +static const struct iio_chan_spec ping_chan_spec[] = { + { + .type = IIO_DISTANCE, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + }, +}; + +static const struct of_device_id of_ping_match[] = { + { .compatible = "parallax,ping", .data = &pa_ping_cfg}, + { .compatible = "parallax,laserping", .data = &pa_ping_cfg}, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_ping_match); + +static int ping_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct ping_data *data; + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(dev, sizeof(struct ping_data)); + if (!indio_dev) { + dev_err(dev, "failed to allocate IIO device\n"); + return -ENOMEM; + } + + data = iio_priv(indio_dev); + data->dev = dev; + data->cfg = of_device_get_match_data(dev); + + mutex_init(&data->lock); + init_completion(&data->rising); + init_completion(&data->falling); + + data->gpiod_ping = devm_gpiod_get(dev, "ping", GPIOD_OUT_LOW); + if (IS_ERR(data->gpiod_ping)) { + dev_err(dev, "failed to get ping-gpios: err=%ld\n", + PTR_ERR(data->gpiod_ping)); + return PTR_ERR(data->gpiod_ping); + } + + if (gpiod_cansleep(data->gpiod_ping)) { + dev_err(data->dev, "cansleep-GPIOs not supported\n"); + return -ENODEV; + } + + platform_set_drvdata(pdev, indio_dev); + + indio_dev->name = "ping"; + indio_dev->dev.parent = &pdev->dev; + indio_dev->info = &ping_iio_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ping_chan_spec; + indio_dev->num_channels = ARRAY_SIZE(ping_chan_spec); + + return devm_iio_device_register(dev, indio_dev); +} + +static struct platform_driver ping_driver = { + .probe = ping_probe, + .driver = { + .name = "ping-gpio", + .of_match_table = of_ping_match, + }, +}; + +module_platform_driver(ping_driver); + +MODULE_AUTHOR("Andreas Klinger "); +MODULE_DESCRIPTION("PING sensors for distance measuring using one GPIOs"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ping"); From 075a1e87d1e2358d0b0301ac8f8e7f25051decf1 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Mon, 2 Dec 2019 06:18:36 -0800 Subject: [PATCH 036/353] staging/octeon: Mark Ethernet driver as BROKEN The code doesn't compile due to incompatible pointer errors such as drivers/staging/octeon/ethernet-tx.c:649:50: error: passing argument 1 of 'cvmx_wqe_get_grp' from incompatible pointer type This is due to mixing, for example, cvmx_wqe_t with 'struct cvmx_wqe'. Unfortunately, one can not just revert the primary offending commit, as doing so results in secondary errors. This is made worse by the fact that the "removed" typedefs still exist and are used widely outside the staging directory, making the entire set of "remove typedef" changes pointless and wrong. Reflect reality and mark the driver as BROKEN. Fixes: ef1fe6b7369a ("staging: octeon: remove typedef declaration for cvmx_wqe") Fixes: 73aef0c9d2c6 ("staging: octeon: remove typedef declaration for cvmx_helper_link_info") Cc: Wambui Karuga Cc: Julia Lawall Signed-off-by: Guenter Roeck Link: https://lore.kernel.org/r/20191202141836.9363-1-linux@roeck-us.net Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/octeon/Kconfig b/drivers/staging/octeon/Kconfig index 5319909eb2f6..e7f4ddcc1361 100644 --- a/drivers/staging/octeon/Kconfig +++ b/drivers/staging/octeon/Kconfig @@ -3,6 +3,7 @@ config OCTEON_ETHERNET tristate "Cavium Networks Octeon Ethernet support" depends on CAVIUM_OCTEON_SOC || COMPILE_TEST depends on NETDEVICES + depends on BROKEN select PHYLIB select MDIO_OCTEON help From 856be41e446a6918fc665399061f4ec75b580501 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Fri, 22 Nov 2019 20:52:03 +0000 Subject: [PATCH 037/353] staging: wilc1000: remove unused compile time featurization Removed the unused compile type featurization. It's not recommended to have compile type feature. Currently removing these defines as they are not used. If any of these parameters are needed later should be added using run time feature. Signed-off-by: Ajay Singh Link: https://lore.kernel.org/r/20191122205153.30723-2-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wlan.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/drivers/staging/wilc1000/wlan.c b/drivers/staging/wilc1000/wlan.c index d3de76126b78..ba5446724c93 100644 --- a/drivers/staging/wilc1000/wlan.c +++ b/drivers/staging/wilc1000/wlan.c @@ -890,29 +890,6 @@ int wilc_wlan_start(struct wilc *wilc) if (wilc->io_type == WILC_HIF_SDIO && wilc->dev_irq_num) reg |= WILC_HAVE_SDIO_IRQ_GPIO; -#ifdef WILC_DISABLE_PMU -#else - reg |= WILC_HAVE_USE_PMU; -#endif - -#ifdef WILC_SLEEP_CLK_SRC_XO - reg |= WILC_HAVE_SLEEP_CLK_SRC_XO; -#elif defined WILC_SLEEP_CLK_SRC_RTC - reg |= WILC_HAVE_SLEEP_CLK_SRC_RTC; -#endif - -#ifdef WILC_EXT_PA_INV_TX_RX - reg |= WILC_HAVE_EXT_PA_INV_TX_RX; -#endif - reg |= WILC_HAVE_USE_IRQ_AS_HOST_WAKE; - reg |= WILC_HAVE_LEGACY_RF_SETTINGS; -#ifdef XTAL_24 - reg |= WILC_HAVE_XTAL_24; -#endif -#ifdef DISABLE_WILC_UART - reg |= WILC_HAVE_DISABLE_WILC_UART; -#endif - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg); if (!ret) { release_bus(wilc, WILC_BUS_RELEASE_ONLY); From a02a9897cd6dd8b8b45162c8edd02ae924382b4b Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Fri, 22 Nov 2019 20:52:04 +0000 Subject: [PATCH 038/353] staging: wilc1000: use kernel provided struct cast to extract mac header To parse the mac header make use of *struct ieee80211_hdr* instead of extracting individual fields separately using pointer operation. Signed-off-by: Ajay Singh Link: https://lore.kernel.org/r/20191122205153.30723-3-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/netdev.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/netdev.c b/drivers/staging/wilc1000/netdev.c index d2c0b0f7cf63..3fd8e008f733 100644 --- a/drivers/staging/wilc1000/netdev.c +++ b/drivers/staging/wilc1000/netdev.c @@ -96,21 +96,18 @@ void wilc_mac_indicate(struct wilc *wilc) static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header) { - u8 *bssid, *bssid1; struct net_device *ndev = NULL; struct wilc_vif *vif; - - bssid = mac_header + 10; - bssid1 = mac_header + 4; + struct ieee80211_hdr *h = (struct ieee80211_hdr *)mac_header; list_for_each_entry_rcu(vif, &wilc->vif_list, list) { if (vif->mode == WILC_STATION_MODE) - if (ether_addr_equal_unaligned(bssid, vif->bssid)) { + if (ether_addr_equal_unaligned(h->addr2, vif->bssid)) { ndev = vif->ndev; goto out; } if (vif->mode == WILC_AP_MODE) - if (ether_addr_equal_unaligned(bssid1, vif->bssid)) { + if (ether_addr_equal_unaligned(h->addr1, vif->bssid)) { ndev = vif->ndev; goto out; } From baf3f2f9d0bf747023c1d1fb197dd4e621ca3fce Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Fri, 22 Nov 2019 20:52:05 +0000 Subject: [PATCH 039/353] staging: wilc1000: use GENMASK to extract wid type Refactor code by make use of 'GENMASK' to extract the WID type from buffer received from firmware. Signed-off-by: Ajay Singh Link: https://lore.kernel.org/r/20191122205153.30723-4-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wlan.h | 1 + drivers/staging/wilc1000/wlan_cfg.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/wlan.h b/drivers/staging/wilc1000/wlan.h index 1f6957cf2e9c..44ae6ed6882c 100644 --- a/drivers/staging/wilc1000/wlan.h +++ b/drivers/staging/wilc1000/wlan.h @@ -197,6 +197,7 @@ #define IS_MANAGMEMENT_CALLBACK 0x080 #define IS_MGMT_STATUS_SUCCES 0x040 +#define WILC_WID_TYPE GENMASK(15, 12) /******************************************** * * Tx/Rx Queue Structure diff --git a/drivers/staging/wilc1000/wlan_cfg.c b/drivers/staging/wilc1000/wlan_cfg.c index 6f6b286788d1..2538435b82fd 100644 --- a/drivers/staging/wilc1000/wlan_cfg.c +++ b/drivers/staging/wilc1000/wlan_cfg.c @@ -4,6 +4,7 @@ * All rights reserved. */ +#include #include "wlan_if.h" #include "wlan.h" #include "wlan_cfg.h" @@ -132,7 +133,6 @@ static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size) * ********************************************/ -#define GET_WID_TYPE(wid) (((wid) >> 12) & 0x7) static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size) { u16 wid; @@ -142,7 +142,7 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size) i = 0; wid = get_unaligned_le16(info); - switch (GET_WID_TYPE(wid)) { + switch (FIELD_GET(WILC_WID_TYPE, wid)) { case WID_CHAR: do { if (wl->cfg.b[i].id == WID_NIL) @@ -244,7 +244,7 @@ static void wilc_wlan_parse_info_frame(struct wilc *wl, u8 *info) int wilc_wlan_cfg_set_wid(u8 *frame, u32 offset, u16 id, u8 *buf, int size) { - u8 type = (id >> 12) & 0xf; + u8 type = FIELD_GET(WILC_WID_TYPE, id); int ret = 0; switch (type) { @@ -290,7 +290,7 @@ int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id) int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size) { - u32 type = (wid >> 12) & 0xf; + u8 type = FIELD_GET(WILC_WID_TYPE, wid); int i, ret = 0; i = 0; From eb00d734bc78368106ca4de4703d368cd123f6df Mon Sep 17 00:00:00 2001 From: Susarla Nikhilesh Date: Tue, 3 Dec 2019 20:00:23 +0530 Subject: [PATCH 040/353] staging: exfat: fix spelling mistake CHECK: 'propogate' may be misspelled - perhaps 'propagate'? FILE: drivers/staging/exfat/exfat_super.c:1484 CHECK: 'propogate' may be misspelled - perhaps 'propagate'? FILE: drivers/staging/exfat/exfat_super.c:1551 Signed-off-by: Susarla Nikhilesh Link: https://lore.kernel.org/r/20191203143023.2786-1-nikhilesh1294@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 6e481908c59f..d1c1e50fb492 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -1481,7 +1481,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) count = count_dos_name_entries(sb, &dir, TYPE_DIR); if (count < 0) { - ret = count; /* propogate error upward */ + ret = count; /* propagate error upward */ goto out; } info->NumSubdirs = count; @@ -1548,7 +1548,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) count = count_dos_name_entries(sb, &dir, TYPE_DIR); if (count < 0) { - ret = count; /* propogate error upward */ + ret = count; /* propagate error upward */ goto out; } info->NumSubdirs += count; From 9a92d02c3f0b6248b5447dc84637a8d37ba7db28 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Fri, 6 Dec 2019 15:55:15 +0800 Subject: [PATCH 041/353] staging: rts5208: add missed pci_release_regions The driver forgets to call pci_release_regions() in probe failure and remove. Add the missed calls to fix it. Signed-off-by: Chuhong Yuan Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20191206075515.18581-1-hslester96@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index cb95ad6fa4f9..15fc96b42032 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -831,7 +831,8 @@ static int rtsx_probe(struct pci_dev *pci, host = scsi_host_alloc(&rtsx_host_template, sizeof(*dev)); if (!host) { dev_err(&pci->dev, "Unable to allocate the scsi host\n"); - return -ENOMEM; + err = -ENOMEM; + goto scsi_host_alloc_fail; } dev = host_to_rtsx(host); @@ -971,7 +972,8 @@ ioremap_fail: kfree(dev->chip); chip_alloc_fail: dev_err(&pci->dev, "%s failed\n", __func__); - +scsi_host_alloc_fail: + pci_release_regions(pci); return err; } @@ -983,6 +985,7 @@ static void rtsx_remove(struct pci_dev *pci) quiesce_and_remove_host(dev); release_everything(dev); + pci_release_regions(pci); } /* PCI IDs */ From f41e1a0a9462fcc0d4423600f6f6e6fabd2e8b16 Mon Sep 17 00:00:00 2001 From: Dorothea Ehrl Date: Wed, 27 Nov 2019 13:30:48 +0100 Subject: [PATCH 042/353] staging/qlge: remove initialising of static local variable This patch fixes "ERROR: do not initialise statics to 0" by checkpatch.pl. Signed-off-by: Dorothea Ehrl Co-developed-by: Vanessa Hack Signed-off-by: Vanessa Hack Link: https://lore.kernel.org/r/20191127123052.16424-1-dorothea.ehrl@fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/qlge/qlge_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c index 6ad4515311f7..587102aa7fbf 100644 --- a/drivers/staging/qlge/qlge_main.c +++ b/drivers/staging/qlge/qlge_main.c @@ -4578,7 +4578,7 @@ static int qlge_probe(struct pci_dev *pdev, { struct net_device *ndev = NULL; struct ql_adapter *qdev = NULL; - static int cards_found = 0; + static int cards_found; int err = 0; ndev = alloc_etherdev_mq(sizeof(struct ql_adapter), From d00208b6464fd1127bf1b82b31789f1ac7d02a4a Mon Sep 17 00:00:00 2001 From: Dorothea Ehrl Date: Wed, 27 Nov 2019 13:30:49 +0100 Subject: [PATCH 043/353] staging/qlge: add blank lines after declarations This patch fixes "WARNING: Missing a blank line after declarations" by checkpatch.pl. Signed-off-by: Dorothea Ehrl Co-developed-by: Vanessa Hack Signed-off-by: Vanessa Hack Link: https://lore.kernel.org/r/20191127123052.16424-2-dorothea.ehrl@fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/qlge/qlge_ethtool.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/staging/qlge/qlge_ethtool.c b/drivers/staging/qlge/qlge_ethtool.c index a6886cc5654c..ea7bc6f2dde2 100644 --- a/drivers/staging/qlge/qlge_ethtool.c +++ b/drivers/staging/qlge/qlge_ethtool.c @@ -332,6 +332,7 @@ quit: static void ql_get_strings(struct net_device *dev, u32 stringset, u8 *buf) { int index; + switch (stringset) { case ETH_SS_TEST: memcpy(buf, *ql_gstrings_test, QLGE_TEST_LEN * ETH_GSTRING_LEN); @@ -412,6 +413,7 @@ static void ql_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *drvinfo) { struct ql_adapter *qdev = netdev_priv(ndev); + strlcpy(drvinfo->driver, qlge_driver_name, sizeof(drvinfo->driver)); strlcpy(drvinfo->version, qlge_driver_version, sizeof(drvinfo->version)); @@ -703,12 +705,14 @@ static int ql_set_pauseparam(struct net_device *netdev, static u32 ql_get_msglevel(struct net_device *ndev) { struct ql_adapter *qdev = netdev_priv(ndev); + return qdev->msg_enable; } static void ql_set_msglevel(struct net_device *ndev, u32 value) { struct ql_adapter *qdev = netdev_priv(ndev); + qdev->msg_enable = value; } From 2d060684ab4c2a9078c63a00892037dd4cfa6966 Mon Sep 17 00:00:00 2001 From: Dorothea Ehrl Date: Wed, 27 Nov 2019 13:30:50 +0100 Subject: [PATCH 044/353] staging/qlge: add braces to conditional statement This patch fixes "CHECK: braces {} should be used on all arms of this statement" by checkpatch.pl. Signed-off-by: Dorothea Ehrl Co-developed-by: Vanessa Hack Signed-off-by: Vanessa Hack Link: https://lore.kernel.org/r/20191127123052.16424-3-dorothea.ehrl@fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/qlge/qlge_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c index 587102aa7fbf..f5ab6cc7050a 100644 --- a/drivers/staging/qlge/qlge_main.c +++ b/drivers/staging/qlge/qlge_main.c @@ -178,8 +178,9 @@ int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 err_bit) "register 0x%.08x access error, value = 0x%.08x!.\n", reg, temp); return -EIO; - } else if (temp & bit) + } else if (temp & bit) { return 0; + } udelay(UDELAY_DELAY); } netif_alert(qdev, probe, qdev->ndev, @@ -3731,8 +3732,9 @@ static int ql_adapter_reset(struct ql_adapter *qdev) /* Wait for the NIC and MGMNT FIFOs to empty. */ ql_wait_fifo_empty(qdev); - } else + } else { clear_bit(QL_ASIC_RECOVERY, &qdev->flags); + } ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR); From 0da2d1051931aa15acbdb897606314c84fc81e43 Mon Sep 17 00:00:00 2001 From: Dorothea Ehrl Date: Wed, 27 Nov 2019 13:30:51 +0100 Subject: [PATCH 045/353] staging/qlge: remove braces in conditional statement This patch fixes "WARNING: braces {} are not necessary for single statement blocks" and "WARNING: braces {} are not necessary for any arm of this statement" by checkpatch.pl. Signed-off-by: Dorothea Ehrl Co-developed-by: Vanessa Hack Signed-off-by: Vanessa Hack Link: https://lore.kernel.org/r/20191127123052.16424-4-dorothea.ehrl@fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/qlge/qlge_main.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c index f5ab6cc7050a..d19709bcdc20 100644 --- a/drivers/staging/qlge/qlge_main.c +++ b/drivers/staging/qlge/qlge_main.c @@ -4101,11 +4101,11 @@ static int qlge_change_mtu(struct net_device *ndev, int new_mtu) struct ql_adapter *qdev = netdev_priv(ndev); int status; - if (ndev->mtu == 1500 && new_mtu == 9000) { + if (ndev->mtu == 1500 && new_mtu == 9000) netif_err(qdev, ifup, qdev->ndev, "Changing to jumbo MTU.\n"); - } else if (ndev->mtu == 9000 && new_mtu == 1500) { + else if (ndev->mtu == 9000 && new_mtu == 1500) netif_err(qdev, ifup, qdev->ndev, "Changing to normal MTU.\n"); - } else + else return -EINVAL; queue_delayed_work(qdev->workqueue, @@ -4113,9 +4113,8 @@ static int qlge_change_mtu(struct net_device *ndev, int new_mtu) ndev->mtu = new_mtu; - if (!netif_running(qdev->ndev)) { + if (!netif_running(qdev->ndev)) return 0; - } status = ql_change_rx_buffers(qdev); if (status) { From 2a51470f270fb7bad89a1c2a60bfc5386c395f8f Mon Sep 17 00:00:00 2001 From: Dorothea Ehrl Date: Wed, 27 Nov 2019 13:30:52 +0100 Subject: [PATCH 046/353] staging/qlge: fix block comment coding style This patch fixes: "WARNING: block comment use * on subsequent lines" "WARNING: block comments should align the * on each line" "WARNING: block comments use a trailing */ on a separate line" by checkpatch.pl. Signed-off-by: Dorothea Ehrl Co-developed-by: Vanessa Hack Signed-off-by: Vanessa Hack Link: https://lore.kernel.org/r/20191127123052.16424-5-dorothea.ehrl@fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/qlge/qlge_main.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c index d19709bcdc20..29861f01ca26 100644 --- a/drivers/staging/qlge/qlge_main.c +++ b/drivers/staging/qlge/qlge_main.c @@ -402,8 +402,8 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, (index << MAC_ADDR_IDX_SHIFT) | /* index */ type); /* type */ /* This field should also include the queue id - and possibly the function id. Right now we hardcode - the route field to NIC core. + * and possibly the function id. Right now we hardcode + * the route field to NIC core. */ cam_output = (CAM_OUT_ROUTE_NIC | (qdev-> @@ -683,7 +683,7 @@ static int ql_read_flash_word(struct ql_adapter *qdev, int offset, __le32 *data) FLASH_ADDR, FLASH_ADDR_RDY, FLASH_ADDR_ERR); if (status) goto exit; - /* This data is stored on flash as an array of + /* This data is stored on flash as an array of * __le32. Since ql_read32() returns cpu endian * we need to swap it back. */ @@ -2223,7 +2223,8 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget) "Enter, NAPI POLL cq_id = %d.\n", rx_ring->cq_id); /* Service the TX rings first. They start - * right after the RSS rings. */ + * right after the RSS rings. + */ for (i = qdev->rss_ring_count; i < qdev->rx_ring_count; i++) { trx_ring = &qdev->rx_ring[i]; /* If this TX completion ring belongs to this vector and @@ -2888,7 +2889,8 @@ static void ql_free_rx_resources(struct ql_adapter *qdev, } /* Allocate queues and buffers for this completions queue based - * on the values in the parameter structure. */ + * on the values in the parameter structure. + */ static int ql_alloc_rx_resources(struct ql_adapter *qdev, struct rx_ring *rx_ring) { From a1df271a8652723786923f8314c07ac1e8a35e2f Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 7 Nov 2019 22:32:23 +0800 Subject: [PATCH 047/353] staging: hp100: Use match_string() helper to simplify the code match_string() returns the array index of a matching string. Use it instead of the open-coded implementation. Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20191107143223.44696-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hp/hp100.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/staging/hp/hp100.c b/drivers/staging/hp/hp100.c index 6ec78f5c602f..e2f0b58e5dfd 100644 --- a/drivers/staging/hp/hp100.c +++ b/drivers/staging/hp/hp100.c @@ -339,14 +339,11 @@ static __init int hp100_isa_probe1(struct net_device *dev, int ioaddr) if (sig == NULL) goto err; - for (i = 0; i < ARRAY_SIZE(hp100_isa_tbl); i++) { - if (!strcmp(hp100_isa_tbl[i], sig)) - break; + i = match_string(hp100_isa_tbl, ARRAY_SIZE(hp100_isa_tbl), sig); + if (i < 0) + goto err; - } - - if (i < ARRAY_SIZE(hp100_isa_tbl)) - return hp100_probe1(dev, ioaddr, HP100_BUS_ISA, NULL); + return hp100_probe1(dev, ioaddr, HP100_BUS_ISA, NULL); err: return -ENODEV; From 1f8a6edf8d2f9be4127b2ceb7c6c9cb7a82cc5b8 Mon Sep 17 00:00:00 2001 From: Michael Kupfer Date: Fri, 6 Dec 2019 09:54:32 +0100 Subject: [PATCH 048/353] staging/vc04_services/bcm2835-camera: distinct numeration and names for devices Create a static atomic counter for numerating cameras. Use the Media Subsystem Kernel Internal API to create distinct device-names, so that the camera-number (given by the counter) matches the camera-name. Co-developed-by: Kay Friedrich Signed-off-by: Kay Friedrich Signed-off-by: Michael Kupfer Link: https://lore.kernel.org/r/20191206085432.19962-1-michael.kupfer@fau.de Signed-off-by: Greg Kroah-Hartman --- .../vc04_services/bcm2835-camera/bcm2835-camera.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c index beb6a0063bb8..1ef31a984741 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c +++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c @@ -60,6 +60,9 @@ MODULE_PARM_DESC(max_video_width, "Threshold for video mode"); module_param(max_video_height, int, 0644); MODULE_PARM_DESC(max_video_height, "Threshold for video mode"); +/* camera instance counter */ +static atomic_t camera_instance = ATOMIC_INIT(0); + /* global device data array */ static struct bm2835_mmal_dev *gdev[MAX_BCM2835_CAMERAS]; @@ -1870,7 +1873,6 @@ static int bcm2835_mmal_probe(struct platform_device *pdev) /* v4l2 core mutex used to protect all fops and v4l2 ioctls. */ mutex_init(&dev->mutex); - dev->camera_num = camera; dev->max_width = resolutions[camera][0]; dev->max_height = resolutions[camera][1]; @@ -1886,8 +1888,9 @@ static int bcm2835_mmal_probe(struct platform_device *pdev) dev->capture.fmt = &formats[3]; /* JPEG */ /* v4l device registration */ - snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), - "%s", BM2835_MMAL_MODULE_NAME); + dev->camera_num = v4l2_device_set_name(&dev->v4l2_dev, + BM2835_MMAL_MODULE_NAME, + &camera_instance); ret = v4l2_device_register(NULL, &dev->v4l2_dev); if (ret) { dev_err(&pdev->dev, "%s: could not register V4L2 device: %d\n", From 742e9285f8b4dbf27add1656eebedf3aff6e634c Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Mon, 9 Dec 2019 04:19:08 -0600 Subject: [PATCH 049/353] staging: qlge: Fix CamelCase in qlge.h and qlge_dbg.c This patch addresses CamelCase warnings in qlge.h under struct mpi_coredump_global_header and mpi_coredump_segment_header. As well ass addresses CamelCase warnings in qlge_dbg.c when the structs are used. Signed-off-by: Scott Schafer Link: https://lore.kernel.org/r/20191209101908.23878-1-schaferjscott@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/qlge/qlge.h | 14 +++++++------- drivers/staging/qlge/qlge_dbg.c | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/staging/qlge/qlge.h b/drivers/staging/qlge/qlge.h index 6ec7e3ce3863..57884aac308f 100644 --- a/drivers/staging/qlge/qlge.h +++ b/drivers/staging/qlge/qlge.h @@ -1627,18 +1627,18 @@ enum { #define MPI_COREDUMP_COOKIE 0x5555aaaa struct mpi_coredump_global_header { u32 cookie; - u8 idString[16]; - u32 timeLo; - u32 timeHi; - u32 imageSize; - u32 headerSize; + u8 id_string[16]; + u32 time_lo; + u32 time_hi; + u32 image_size; + u32 header_size; u8 info[220]; }; struct mpi_coredump_segment_header { u32 cookie; - u32 segNum; - u32 segSize; + u32 seg_num; + u32 seg_size; u32 extra; u8 description[16]; }; diff --git a/drivers/staging/qlge/qlge_dbg.c b/drivers/staging/qlge/qlge_dbg.c index 83f34ca43aa4..aac20db565fa 100644 --- a/drivers/staging/qlge/qlge_dbg.c +++ b/drivers/staging/qlge/qlge_dbg.c @@ -702,8 +702,8 @@ static void ql_build_coredump_seg_header( { memset(seg_hdr, 0, sizeof(struct mpi_coredump_segment_header)); seg_hdr->cookie = MPI_COREDUMP_COOKIE; - seg_hdr->segNum = seg_number; - seg_hdr->segSize = seg_size; + seg_hdr->seg_num = seg_number; + seg_hdr->seg_size = seg_size; strncpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1); } @@ -741,12 +741,12 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) memset(&(mpi_coredump->mpi_global_header), 0, sizeof(struct mpi_coredump_global_header)); mpi_coredump->mpi_global_header.cookie = MPI_COREDUMP_COOKIE; - mpi_coredump->mpi_global_header.headerSize = + mpi_coredump->mpi_global_header.header_size = sizeof(struct mpi_coredump_global_header); - mpi_coredump->mpi_global_header.imageSize = + mpi_coredump->mpi_global_header.image_size = sizeof(struct ql_mpi_coredump); - strncpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump", - sizeof(mpi_coredump->mpi_global_header.idString)); + strncpy(mpi_coredump->mpi_global_header.id_string, "MPI Coredump", + sizeof(mpi_coredump->mpi_global_header.id_string)); /* Get generic NIC reg dump */ ql_build_coredump_seg_header(&mpi_coredump->nic_regs_seg_hdr, @@ -1231,12 +1231,12 @@ static void ql_gen_reg_dump(struct ql_adapter *qdev, memset(&(mpi_coredump->mpi_global_header), 0, sizeof(struct mpi_coredump_global_header)); mpi_coredump->mpi_global_header.cookie = MPI_COREDUMP_COOKIE; - mpi_coredump->mpi_global_header.headerSize = + mpi_coredump->mpi_global_header.header_size = sizeof(struct mpi_coredump_global_header); - mpi_coredump->mpi_global_header.imageSize = + mpi_coredump->mpi_global_header.image_size = sizeof(struct ql_reg_dump); - strncpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump", - sizeof(mpi_coredump->mpi_global_header.idString)); + strncpy(mpi_coredump->mpi_global_header.id_string, "MPI Coredump", + sizeof(mpi_coredump->mpi_global_header.id_string)); /* segment 16 */ From 1544f55add5c8a5b463b7ae6346ab6df650fdffd Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 23 Nov 2019 16:16:33 +0100 Subject: [PATCH 050/353] staging: rtl8188eu: remove unnecessary parentheses in rtw_pwrctrl.c Remove unnecessary parentheses reported by checkpatch. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20191123151635.155138-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_pwrctrl.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c index 03dc7e5fcc38..010a0cdf7940 100644 --- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c @@ -154,8 +154,8 @@ void ips_enter(struct adapter *padapter) int ips_leave(struct adapter *padapter) { struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct security_priv *psecuritypriv = &(padapter->securitypriv); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct security_priv *psecuritypriv = &padapter->securitypriv; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; int result = _SUCCESS; int keyid; @@ -200,7 +200,7 @@ int ips_leave(struct adapter *padapter) static bool rtw_pwr_unassociated_idle(struct adapter *adapter) { - struct mlme_priv *pmlmepriv = &(adapter->mlmepriv); + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; bool ret = false; if (time_after_eq(adapter->pwrctrlpriv.ips_deny_time, jiffies)) @@ -221,7 +221,7 @@ exit: void rtw_ps_processor(struct adapter *padapter) { struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; enum rt_rf_power_state rfpwrstate; pwrpriv->ps_processing = true; @@ -336,7 +336,7 @@ static u8 PS_RDY_CHECK(struct adapter *padapter) { unsigned long curr_time, delta_time; struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; curr_time = jiffies; delta_time = curr_time - pwrpriv->DelayLPSLastTimeStamp; @@ -483,7 +483,7 @@ void LPS_Leave(struct adapter *padapter) /* */ void LeaveAllPowerSaveMode(struct adapter *Adapter) { - struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; u8 enqueue = 0; if (check_fwstate(pmlmepriv, _FW_LINKED)) From 4905084a07fc133605088fc1d65401c6ba4a5a76 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 23 Nov 2019 16:16:34 +0100 Subject: [PATCH 051/353] staging: rtl8188eu: cleanup declarations in rtw_pwrctrl.c Replace tabs with spaces in declarations to cleanup whitespace. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20191123151635.155138-2-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_pwrctrl.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c index 010a0cdf7940..8e99e10c1fd4 100644 --- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c @@ -282,7 +282,7 @@ static void pwr_state_check_handler(struct timer_list *t) */ void rtw_set_rpwm(struct adapter *padapter, u8 pslv) { - u8 rpwm; + u8 rpwm; struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; pslv = PS_STATE(pslv); @@ -335,8 +335,8 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv) static u8 PS_RDY_CHECK(struct adapter *padapter) { unsigned long curr_time, delta_time; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; curr_time = jiffies; delta_time = curr_time - pwrpriv->DelayLPSLastTimeStamp; @@ -437,7 +437,7 @@ s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms) /* */ void LPS_Enter(struct adapter *padapter) { - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; if (!PS_RDY_CHECK(padapter)) return; @@ -463,7 +463,7 @@ void LPS_Enter(struct adapter *padapter) /* Leave the leisure power save mode. */ void LPS_Leave(struct adapter *padapter) { - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; if (pwrpriv->bLeisurePs) { if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) { @@ -483,8 +483,8 @@ void LPS_Leave(struct adapter *padapter) /* */ void LeaveAllPowerSaveMode(struct adapter *Adapter) { - struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; - u8 enqueue = 0; + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + u8 enqueue = 0; if (check_fwstate(pmlmepriv, _FW_LINKED)) rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue); @@ -611,7 +611,7 @@ exit: int rtw_pm_set_lps(struct adapter *padapter, u8 mode) { - int ret = 0; + int ret = 0; struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; if (mode < PS_MODE_NUM) { From a426b982be18eac979a26deca9ae8cb7f0082101 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 23 Nov 2019 16:16:35 +0100 Subject: [PATCH 052/353] staging: rtl8188eu: remove return variable from rtw_pwr_unassociated_idle Function rtw_pwr_unassociated_idle returns boolean values. Remove the return variable ret and the exit label to simplify the function a little bit. Return true or false directly instead. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20191123151635.155138-3-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_pwrctrl.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c index 8e99e10c1fd4..c4f58507dbfd 100644 --- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c @@ -201,21 +201,17 @@ int ips_leave(struct adapter *padapter) static bool rtw_pwr_unassociated_idle(struct adapter *adapter) { struct mlme_priv *pmlmepriv = &adapter->mlmepriv; - bool ret = false; if (time_after_eq(adapter->pwrctrlpriv.ips_deny_time, jiffies)) - goto exit; + return false; if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR) || check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS) || check_fwstate(pmlmepriv, WIFI_AP_STATE) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)) - goto exit; + return false; - ret = true; - -exit: - return ret; + return true; } void rtw_ps_processor(struct adapter *padapter) From 0988161a9828a320b8e6a780f3b4af64f7c3e257 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Mon, 25 Nov 2019 16:51:31 +0100 Subject: [PATCH 053/353] staging: most: fix improper SPDX-License comment style This patch uses '/*' in the SPDX comment. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1574697096-2942-2-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h index 49859aef98df..1380e7586376 100644 --- a/drivers/staging/most/core.h +++ b/drivers/staging/most/core.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * most.h - API for component and adapter drivers * From 7e6d24d9bca792fed090d7c1069bc16e4b04413c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Dec 2019 15:13:53 +0100 Subject: [PATCH 054/353] staging: most: Use managed buffer allocation Clean up the driver with the new managed buffer allocation API. Also remove the unnecessary checks of channels in hw_params callback as this is guaranteed by the hw constraints in anyway. After these cleanups, the hw_params and hw_free callbacks became empty, hence dropped. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20191210141356.18074-2-tiwai@suse.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/sound/sound.c | 44 +----------------------------- 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 723d0bd1cc21..7c212c0db980 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -322,45 +322,6 @@ static int pcm_close(struct snd_pcm_substream *substream) return 0; } -/** - * pcm_hw_params - implements hw_params callback function for PCM middle layer - * @substream: sub-stream pointer - * @hw_params: contains the hardware parameters set by the application - * - * This is called when the hardware parameters is set by the application, that - * is, once when the buffer size, the period size, the format, etc. are defined - * for the PCM substream. Many hardware setups should be done is this callback, - * including the allocation of buffers. - * - * Returns 0 on success or error code otherwise. - */ -static int pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct channel *channel = substream->private_data; - - if ((params_channels(hw_params) > channel->pcm_hardware.channels_max) || - (params_channels(hw_params) < channel->pcm_hardware.channels_min)) { - pr_err("Requested number of channels not supported.\n"); - return -EINVAL; - } - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); -} - -/** - * pcm_hw_free - implements hw_free callback function for PCM middle layer - * @substream: substream pointer - * - * This is called to release the resources allocated via hw_params. - * This function will be always called before the close callback is called. - * - * Returns 0 on success or error code otherwise. - */ -static int pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - /** * pcm_prepare - implements prepare callback function for PCM middle layer * @substream: substream pointer @@ -463,8 +424,6 @@ static const struct snd_pcm_ops pcm_ops = { .open = pcm_open, .close = pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_hw_params, - .hw_free = pcm_hw_free, .prepare = pcm_prepare, .trigger = pcm_trigger, .pointer = pcm_pointer, @@ -661,8 +620,7 @@ skip_adpt_alloc: pcm->private_data = channel; strscpy(pcm->name, device_name, sizeof(pcm->name)); snd_pcm_set_ops(pcm, direction, &pcm_ops); - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC, - NULL, 0, 0); + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0); return 0; From 3ad10e575451cda0abc5498b614cbcdc10517ec9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Dec 2019 15:13:54 +0100 Subject: [PATCH 055/353] staging: bcm2835-audio: Use managed buffer allocation Clean up the driver with the new managed buffer allocation API. The hw_params and hw_free callbacks became superfluous and dropped. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20191210141356.18074-3-tiwai@suse.de Signed-off-by: Greg Kroah-Hartman --- .../vc04_services/bcm2835-audio/bcm2835-pcm.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c index 826016c3431a..97726b190bc5 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c @@ -193,17 +193,6 @@ static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream) return 0; } -static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); -} - -static int snd_bcm2835_pcm_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream) { struct bcm2835_chip *chip = snd_pcm_substream_chip(substream); @@ -317,8 +306,6 @@ static const struct snd_pcm_ops snd_bcm2835_playback_ops = { .open = snd_bcm2835_playback_open, .close = snd_bcm2835_playback_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_bcm2835_pcm_hw_params, - .hw_free = snd_bcm2835_pcm_hw_free, .prepare = snd_bcm2835_pcm_prepare, .trigger = snd_bcm2835_pcm_trigger, .pointer = snd_bcm2835_pcm_pointer, @@ -329,8 +316,6 @@ static const struct snd_pcm_ops snd_bcm2835_playback_spdif_ops = { .open = snd_bcm2835_playback_spdif_open, .close = snd_bcm2835_playback_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_bcm2835_pcm_hw_params, - .hw_free = snd_bcm2835_pcm_hw_free, .prepare = snd_bcm2835_pcm_prepare, .trigger = snd_bcm2835_pcm_trigger, .pointer = snd_bcm2835_pcm_pointer, @@ -362,7 +347,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, const char *name, spdif ? &snd_bcm2835_playback_spdif_ops : &snd_bcm2835_playback_ops); - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, chip->card->dev, 128 * 1024, 128 * 1024); if (spdif) From 0a2eb63de28fe3aef3a42c00a27f80689d9ce662 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Dec 2019 15:13:55 +0100 Subject: [PATCH 056/353] staging: most: Drop superfluous ioctl PCM ops PCM core deals the empty ioctl field now as default. Let's kill the redundant lines. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20191210141356.18074-4-tiwai@suse.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/sound/sound.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 7c212c0db980..1ccfcb8f78b9 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -423,7 +423,6 @@ static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) static const struct snd_pcm_ops pcm_ops = { .open = pcm_open, .close = pcm_close, - .ioctl = snd_pcm_lib_ioctl, .prepare = pcm_prepare, .trigger = pcm_trigger, .pointer = pcm_pointer, From de7c18bd2764a5efff7a3bac0ac0247943ef2975 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 10 Dec 2019 15:13:56 +0100 Subject: [PATCH 057/353] staging: bcm2835-audio: Drop superfluous ioctl PCM ops PCM core deals the empty ioctl field now as default. Let's kill the redundant lines. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20191210141356.18074-5-tiwai@suse.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c index 97726b190bc5..33485184a98a 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c @@ -305,7 +305,6 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_substream *substream) static const struct snd_pcm_ops snd_bcm2835_playback_ops = { .open = snd_bcm2835_playback_open, .close = snd_bcm2835_playback_close, - .ioctl = snd_pcm_lib_ioctl, .prepare = snd_bcm2835_pcm_prepare, .trigger = snd_bcm2835_pcm_trigger, .pointer = snd_bcm2835_pcm_pointer, @@ -315,7 +314,6 @@ static const struct snd_pcm_ops snd_bcm2835_playback_ops = { static const struct snd_pcm_ops snd_bcm2835_playback_spdif_ops = { .open = snd_bcm2835_playback_spdif_open, .close = snd_bcm2835_playback_close, - .ioctl = snd_pcm_lib_ioctl, .prepare = snd_bcm2835_pcm_prepare, .trigger = snd_bcm2835_pcm_trigger, .pointer = snd_bcm2835_pcm_pointer, From 68468503e000d70f71695f5a0050957f66e51416 Mon Sep 17 00:00:00 2001 From: Andreas Hellmich Date: Fri, 29 Nov 2019 10:39:39 +0100 Subject: [PATCH 058/353] staging: rtl8723bs: Fix spelling errors Fix spelling errors. Co-developed-by: Annika Knepper Signed-off-by: Annika Knepper Signed-off-by: Andreas Hellmich Link: https://lore.kernel.org/r/20191129093939.2782-1-dy26hofu@stud.informatik.uni-erlangen.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 36 +++++++++---------- .../staging/rtl8723bs/hal/HalPhyRf_8723B.c | 6 ++-- .../staging/rtl8723bs/hal/rtl8723b_hal_init.c | 14 ++++---- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index 5e687f6d2c3e..81062ec3f086 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -207,7 +207,7 @@ static RT_CHANNEL_PLAN_MAP RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { {0x02, 0x1F}, /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */ }; -static RT_CHANNEL_PLAN_MAP RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; /* use the conbination for max channel numbers */ +static RT_CHANNEL_PLAN_MAP RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; /* use the combination for max channel numbers */ /* * Search the @param ch in given @param ch_set @@ -2265,7 +2265,7 @@ inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv) /**************************************************************************** -Following are some TX fuctions for WiFi MLME +Following are some TX functions for WiFi MLME *****************************************************************************/ @@ -2956,7 +2956,7 @@ exit: return ret; } -/* if psta == NULL, indiate we are station(client) now... */ +/* if psta == NULL, indicate we are station(client) now... */ void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status) { struct xmit_frame *pmgntframe; @@ -3358,7 +3358,7 @@ void issue_assocreq(struct adapter *padapter) if ((!padapter->registrypriv.wifi_spec) && (!memcmp(pIE->data, WPS_OUI, 4))) { /* Commented by Kurt 20110629 */ /* In some older APs, WPS handshake */ - /* would be fail if we append vender extensions informations to AP */ + /* would be fail if we append vender extensions information to AP */ vs_ie_length = 14; } @@ -3406,7 +3406,7 @@ exit: rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len); } -/* when wait_ack is ture, this function shoule be called at process context */ +/* when wait_ack is true, this function should be called at process context */ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, bool wait_ack) { @@ -3481,7 +3481,7 @@ exit: /* * [IMPORTANT] Don't call this function in interrupt context * - * When wait_ms > 0, this function shoule be called at process context + * When wait_ms > 0, this function should be called at process context * da == NULL for station mode */ int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms) @@ -3493,7 +3493,7 @@ int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int pow struct sta_info *psta; - /* da == NULL, assum it's null data for sta to ap*/ + /* da == NULL, assume it's null data for sta to ap*/ if (!da) da = get_my_bssid(&(pmlmeinfo->network)); @@ -3558,14 +3558,14 @@ s32 issue_nulldata_in_interrupt(struct adapter *padapter, u8 *da) pmlmeext = &padapter->mlmeextpriv; pmlmeinfo = &pmlmeext->mlmext_info; - /* da == NULL, assum it's null data for sta to ap*/ + /* da == NULL, assume it's null data for sta to ap*/ if (!da) da = get_my_bssid(&(pmlmeinfo->network)); return _issue_nulldata(padapter, da, 0, false); } -/* when wait_ack is ture, this function shoule be called at process context */ +/* when wait_ack is true, this function should be called at process context */ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, bool wait_ack) { @@ -3644,7 +3644,7 @@ exit: return ret; } -/* when wait_ms >0 , this function shoule be called at process context */ +/* when wait_ms >0 , this function should be called at process context */ /* da == NULL for station mode */ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms) { @@ -3653,7 +3653,7 @@ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - /* da == NULL, assum it's null data for sta to ap*/ + /* da == NULL, assume it's null data for sta to ap*/ if (!da) da = get_my_bssid(&(pmlmeinfo->network)); @@ -4264,7 +4264,7 @@ unsigned int send_beacon(struct adapter *padapter) /**************************************************************************** -Following are some utitity fuctions for WiFi MLME +Following are some utility functions for WiFi MLME *****************************************************************************/ @@ -4568,7 +4568,7 @@ u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, str } #endif - /* mark bss info receving from nearby channel as SignalQuality 101 */ + /* mark bss info receiving from nearby channel as SignalQuality 101 */ if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter)) bssid->PhyInfo.SignalQuality = 101; @@ -4589,7 +4589,7 @@ void start_create_ibss(struct adapter *padapter) /* update wireless mode */ update_wireless_mode(padapter); - /* udpate capability */ + /* update capability */ caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork); update_capinfo(padapter, caps); if (caps&cap_IBSS) {/* adhoc master */ @@ -4644,7 +4644,7 @@ void start_clnt_join(struct adapter *padapter) /* update wireless mode */ update_wireless_mode(padapter); - /* udpate capability */ + /* update capability */ caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork); update_capinfo(padapter, caps); if (caps&cap_ESS) { @@ -5441,7 +5441,7 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res) /* turn on dynamic functions */ Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); - /* update IOT-releated issue */ + /* update IOT-related issue */ update_IOT_info(padapter); rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates); @@ -5449,7 +5449,7 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res) /* BCN interval */ rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval)); - /* udpate capability */ + /* update capability */ update_capinfo(padapter, pmlmeinfo->capability); /* WMM, Update EDCA param */ @@ -6385,7 +6385,7 @@ u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf) Save_DM_Func_Flag(padapter); Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); - /* config the initial gain under scaning, need to write the BB registers */ + /* config the initial gain under scanning, need to write the BB registers */ initialgain = 0x1e; rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c index 1ca9063a269f..106bfd670701 100644 --- a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c +++ b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c @@ -82,7 +82,7 @@ static void setIqkMatrix_8723B( /* if (RFPath == ODM_RF_PATH_A) */ switch (RFPath) { case ODM_RF_PATH_A: - /* wirte new elements A, C, D to regC80 and regC94, element B is always 0 */ + /* write new elements A, C, D to regC80 and regC94, element B is always 0 */ value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A; PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, bMaskDWord, value32); @@ -93,7 +93,7 @@ static void setIqkMatrix_8723B( PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT24, value32); break; case ODM_RF_PATH_B: - /* wirte new elements A, C, D to regC88 and regC9C, element B is always 0 */ + /* write new elements A, C, D to regC88 and regC9C, element B is always 0 */ value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A; PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord, value32); @@ -166,7 +166,7 @@ void DoIQK_8723B( /*----------------------------------------------------------------------------- * Function: odm_TxPwrTrackSetPwr88E() * - * Overview: 88E change all channel tx power accordign to flag. + * Overview: 88E change all channel tx power according to flag. * OFDM & CCK are all different. * * Input: NONE diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c index 66127f6c8e4d..06c22ccfb2fd 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c @@ -750,7 +750,7 @@ static void Hal_BT_EfusePowerSwitch( rtw_write8(padapter, 0x6B, tempval); /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */ - /* So don't wirte 0x6A[14]= 1 and 0x6A[15]= 0 together! */ + /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */ msleep(1); /* disable BT output isolation */ /* 0x6A[15] = 0 */ @@ -765,7 +765,7 @@ static void Hal_BT_EfusePowerSwitch( rtw_write8(padapter, 0x6B, tempval); /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */ - /* So don't wirte 0x6A[14]= 1 and 0x6A[15]= 0 together! */ + /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */ /* disable BT power cut */ /* 0x6A[14] = 1 */ @@ -1231,7 +1231,7 @@ static u16 hal_EfuseGetCurrentSize_WiFi( goto exit; error: - /* report max size to prevent wirte efuse */ + /* report max size to prevent write efuse */ EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &efuse_addr, bPseudoTest); exit: @@ -2237,7 +2237,7 @@ void rtl8723b_InitAntenna_Selection(struct adapter *padapter) u8 val; val = rtw_read8(padapter, REG_LEDCFG2); - /* Let 8051 take control antenna settting */ + /* Let 8051 take control antenna setting */ val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */ rtw_write8(padapter, REG_LEDCFG2, val); } @@ -3193,7 +3193,7 @@ static void rtl8723b_fill_default_txdesc( /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */ /* (1) The sequence number of each non-Qos frame / broadcast / multicast / */ - /* mgnt frame should be controled by Hw because Fw will also send null data */ + /* mgnt frame should be controlled by Hw because Fw will also send null data */ /* which we cannot control when Fw LPS enable. */ /* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */ /* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */ @@ -3543,7 +3543,7 @@ static void hw_var_set_mlme_sitesurvey(struct adapter *padapter, u8 variable, u8 rtw_write8(padapter, reg_bcn_ctl, val8); } - /* Save orignal RRSR setting. */ + /* Save original RRSR setting. */ pHalData->RegRRSR = rtw_read16(padapter, REG_RRSR); } else { /* sitesurvey done */ @@ -3561,7 +3561,7 @@ static void hw_var_set_mlme_sitesurvey(struct adapter *padapter, u8 variable, u8 value_rcr |= rcr_clear_bit; rtw_write32(padapter, REG_RCR, value_rcr); - /* Restore orignal RRSR setting. */ + /* Restore original RRSR setting. */ rtw_write16(padapter, REG_RRSR, pHalData->RegRRSR); } } From 4d17363db021311d0b5ad533bc9c438ed3177d7c Mon Sep 17 00:00:00 2001 From: Andreas Hellmich Date: Fri, 29 Nov 2019 10:39:41 +0100 Subject: [PATCH 059/353] staging: rtl8723bs: Fix line length Fix some line length errors. Co-developed-by: Annika Knepper Signed-off-by: Annika Knepper Signed-off-by: Andreas Hellmich Link: https://lore.kernel.org/r/20191129093939.2782-2-dy26hofu@stud.informatik.uni-erlangen.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 24 +++++++------- .../staging/rtl8723bs/hal/HalPhyRf_8723B.c | 10 ++++-- .../staging/rtl8723bs/hal/rtl8723b_hal_init.c | 32 ++++++++++--------- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index 81062ec3f086..c642825ca8ef 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -207,10 +207,10 @@ static RT_CHANNEL_PLAN_MAP RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { {0x02, 0x1F}, /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */ }; -static RT_CHANNEL_PLAN_MAP RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; /* use the combination for max channel numbers */ + /* use the combination for max channel numbers */ +static RT_CHANNEL_PLAN_MAP RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; -/* - * Search the @param ch in given @param ch_set +/* Search the @param ch in given @param ch_set * @ch_set: the given channel set * @ch: the given channel number * @@ -229,8 +229,7 @@ int rtw_ch_set_search_ch(RT_CHANNEL_INFO *ch_set, const u32 ch) return i; } -/* - * Check the @param ch is fit with setband setting of @param adapter +/* Check the @param ch is fit with setband setting of @param adapter * @adapter: the given adapter * @ch: the given channel number * @@ -3356,9 +3355,11 @@ void issue_assocreq(struct adapter *padapter) (!memcmp(pIE->data, WPS_OUI, 4))) { vs_ie_length = pIE->Length; if ((!padapter->registrypriv.wifi_spec) && (!memcmp(pIE->data, WPS_OUI, 4))) { - /* Commented by Kurt 20110629 */ - /* In some older APs, WPS handshake */ - /* would be fail if we append vender extensions information to AP */ + /* Commented by Kurt 20110629 + * In some older APs, WPS handshake + * would be fail if we append vendor + * extensions information to AP + */ vs_ie_length = 14; } @@ -5379,8 +5380,7 @@ static void rtw_mlmeext_disconnect(struct adapter *padapter) /* set_opmode_cmd(padapter, infra_client_with_mlme); */ - /* - * For safety, prevent from keeping macid sleep. + /* For safety, prevent from keeping macid sleep. * If we can sure all power mode enter/leave are paired, * this check can be removed. * Lucas@20131113 @@ -6385,7 +6385,9 @@ u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf) Save_DM_Func_Flag(padapter); Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); - /* config the initial gain under scanning, need to write the BB registers */ + /* config the initial gain under scanning, need to write the BB + * registers + */ initialgain = 0x1e; rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c index 106bfd670701..338dd0b7a6eb 100644 --- a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c +++ b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** +/***************************************************************************** * * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. * @@ -82,7 +82,9 @@ static void setIqkMatrix_8723B( /* if (RFPath == ODM_RF_PATH_A) */ switch (RFPath) { case ODM_RF_PATH_A: - /* write new elements A, C, D to regC80 and regC94, element B is always 0 */ + /* write new elements A, C, D to regC80 and regC94, + * element B is always 0 + */ value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A; PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XATxIQImbalance, bMaskDWord, value32); @@ -93,7 +95,9 @@ static void setIqkMatrix_8723B( PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, BIT24, value32); break; case ODM_RF_PATH_B: - /* write new elements A, C, D to regC88 and regC9C, element B is always 0 */ + /* write new elements A, C, D to regC88 and regC9C, + * element B is always 0 + */ value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A; PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord, value32); diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c index 06c22ccfb2fd..de8caa6cd418 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c @@ -3191,22 +3191,26 @@ static void rtl8723b_fill_default_txdesc( if (bmcst) ptxdesc->bmc = 1; - /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */ - /* (1) The sequence number of each non-Qos frame / broadcast / multicast / */ - /* mgnt frame should be controlled by Hw because Fw will also send null data */ - /* which we cannot control when Fw LPS enable. */ - /* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */ - /* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */ - /* (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */ - /* 2010.06.23. Added by tynli. */ + /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. + * (1) The sequence number of each non-Qos frame / broadcast / + * multicast / mgnt frame should be controlled by Hw because Fw + * will also send null data which we cannot control when Fw LPS + * enable. + * --> default enable non-Qos data sequense number. 2010.06.23. + * by tynli. + * (2) Enable HW SEQ control for beacon packet, because we use + * Hw beacon. + * (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos + * packets. + * 2010.06.23. Added by tynli. + */ if (!pattrib->qos_en) /* Hw set sequence number */ ptxdesc->en_hwseq = 1; /* HWSEQ_EN */ } -/* - *Description: +/* Description: * - *Parameters: + * Parameters: * pxmitframe xmitframe * pbuf where to fill tx desc */ @@ -4329,8 +4333,7 @@ void GetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val) } } -/* - *Description: +/* Description: * Change default setting of specified variable. */ u8 SetHalDefVar8723B(struct adapter *padapter, enum HAL_DEF_VARIABLE variable, void *pval) @@ -4348,8 +4351,7 @@ u8 SetHalDefVar8723B(struct adapter *padapter, enum HAL_DEF_VARIABLE variable, v return bResult; } -/* - *Description: +/* Description: * Query setting of specified variable. */ u8 GetHalDefVar8723B(struct adapter *padapter, enum HAL_DEF_VARIABLE variable, void *pval) From f10870b05d5edc0652701c6a92eafcab5044795f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 10 Dec 2019 21:59:15 +0100 Subject: [PATCH 060/353] staging: remove isdn capi drivers As described in drivers/staging/isdn/TODO, the drivers are all assumed to be unmaintained and unused now, with gigaset being the last one to stop being maintained after Paul Bolle lost access to an ISDN network. The CAPI subsystem remains for now, as it is still required by bluetooth/cmtp. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20191210210455.3475361-1-arnd@arndb.de Signed-off-by: Greg Kroah-Hartman --- Documentation/isdn/avmb1.rst | 246 -- Documentation/isdn/gigaset.rst | 465 --- Documentation/isdn/hysdn.rst | 196 -- Documentation/isdn/index.rst | 3 - .../userspace-api/ioctl/ioctl-number.rst | 1 - MAINTAINERS | 3 +- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/isdn/Kconfig | 12 - drivers/staging/isdn/Makefile | 8 - drivers/staging/isdn/TODO | 22 - drivers/staging/isdn/avm/Kconfig | 65 - drivers/staging/isdn/avm/Makefile | 12 - drivers/staging/isdn/avm/avm_cs.c | 166 - drivers/staging/isdn/avm/avmcard.h | 581 ---- drivers/staging/isdn/avm/b1.c | 819 ----- drivers/staging/isdn/avm/b1dma.c | 981 ------ drivers/staging/isdn/avm/b1isa.c | 243 -- drivers/staging/isdn/avm/b1pci.c | 416 --- drivers/staging/isdn/avm/b1pcmcia.c | 224 -- drivers/staging/isdn/avm/c4.c | 1317 -------- drivers/staging/isdn/avm/t1isa.c | 594 ---- drivers/staging/isdn/avm/t1pci.c | 259 -- drivers/staging/isdn/gigaset/Kconfig | 62 - drivers/staging/isdn/gigaset/Makefile | 17 - drivers/staging/isdn/gigaset/asyncdata.c | 606 ---- drivers/staging/isdn/gigaset/bas-gigaset.c | 2672 ----------------- drivers/staging/isdn/gigaset/capi.c | 2517 ---------------- drivers/staging/isdn/gigaset/common.c | 1153 ------- drivers/staging/isdn/gigaset/dummyll.c | 74 - drivers/staging/isdn/gigaset/ev-layer.c | 1910 ------------ drivers/staging/isdn/gigaset/gigaset.h | 827 ----- drivers/staging/isdn/gigaset/interface.c | 613 ---- drivers/staging/isdn/gigaset/isocdata.c | 1006 ------- drivers/staging/isdn/gigaset/proc.c | 77 - drivers/staging/isdn/gigaset/ser-gigaset.c | 796 ----- drivers/staging/isdn/gigaset/usb-gigaset.c | 946 ------ drivers/staging/isdn/hysdn/Kconfig | 15 - drivers/staging/isdn/hysdn/Makefile | 12 - drivers/staging/isdn/hysdn/boardergo.c | 445 --- drivers/staging/isdn/hysdn/boardergo.h | 100 - drivers/staging/isdn/hysdn/hycapi.c | 785 ----- drivers/staging/isdn/hysdn/hysdn_boot.c | 400 --- drivers/staging/isdn/hysdn/hysdn_defs.h | 282 -- drivers/staging/isdn/hysdn/hysdn_init.c | 213 -- drivers/staging/isdn/hysdn/hysdn_net.c | 330 -- drivers/staging/isdn/hysdn/hysdn_pof.h | 78 - drivers/staging/isdn/hysdn/hysdn_procconf.c | 411 --- drivers/staging/isdn/hysdn/hysdn_proclog.c | 357 --- drivers/staging/isdn/hysdn/hysdn_sched.c | 197 -- drivers/staging/isdn/hysdn/ince1pc.h | 134 - include/linux/b1pcmcia.h | 21 - include/uapi/linux/gigaset_dev.h | 39 - include/uapi/linux/hysdn_if.h | 34 - 54 files changed, 1 insertion(+), 23764 deletions(-) delete mode 100644 Documentation/isdn/avmb1.rst delete mode 100644 Documentation/isdn/gigaset.rst delete mode 100644 Documentation/isdn/hysdn.rst delete mode 100644 drivers/staging/isdn/Kconfig delete mode 100644 drivers/staging/isdn/Makefile delete mode 100644 drivers/staging/isdn/TODO delete mode 100644 drivers/staging/isdn/avm/Kconfig delete mode 100644 drivers/staging/isdn/avm/Makefile delete mode 100644 drivers/staging/isdn/avm/avm_cs.c delete mode 100644 drivers/staging/isdn/avm/avmcard.h delete mode 100644 drivers/staging/isdn/avm/b1.c delete mode 100644 drivers/staging/isdn/avm/b1dma.c delete mode 100644 drivers/staging/isdn/avm/b1isa.c delete mode 100644 drivers/staging/isdn/avm/b1pci.c delete mode 100644 drivers/staging/isdn/avm/b1pcmcia.c delete mode 100644 drivers/staging/isdn/avm/c4.c delete mode 100644 drivers/staging/isdn/avm/t1isa.c delete mode 100644 drivers/staging/isdn/avm/t1pci.c delete mode 100644 drivers/staging/isdn/gigaset/Kconfig delete mode 100644 drivers/staging/isdn/gigaset/Makefile delete mode 100644 drivers/staging/isdn/gigaset/asyncdata.c delete mode 100644 drivers/staging/isdn/gigaset/bas-gigaset.c delete mode 100644 drivers/staging/isdn/gigaset/capi.c delete mode 100644 drivers/staging/isdn/gigaset/common.c delete mode 100644 drivers/staging/isdn/gigaset/dummyll.c delete mode 100644 drivers/staging/isdn/gigaset/ev-layer.c delete mode 100644 drivers/staging/isdn/gigaset/gigaset.h delete mode 100644 drivers/staging/isdn/gigaset/interface.c delete mode 100644 drivers/staging/isdn/gigaset/isocdata.c delete mode 100644 drivers/staging/isdn/gigaset/proc.c delete mode 100644 drivers/staging/isdn/gigaset/ser-gigaset.c delete mode 100644 drivers/staging/isdn/gigaset/usb-gigaset.c delete mode 100644 drivers/staging/isdn/hysdn/Kconfig delete mode 100644 drivers/staging/isdn/hysdn/Makefile delete mode 100644 drivers/staging/isdn/hysdn/boardergo.c delete mode 100644 drivers/staging/isdn/hysdn/boardergo.h delete mode 100644 drivers/staging/isdn/hysdn/hycapi.c delete mode 100644 drivers/staging/isdn/hysdn/hysdn_boot.c delete mode 100644 drivers/staging/isdn/hysdn/hysdn_defs.h delete mode 100644 drivers/staging/isdn/hysdn/hysdn_init.c delete mode 100644 drivers/staging/isdn/hysdn/hysdn_net.c delete mode 100644 drivers/staging/isdn/hysdn/hysdn_pof.h delete mode 100644 drivers/staging/isdn/hysdn/hysdn_procconf.c delete mode 100644 drivers/staging/isdn/hysdn/hysdn_proclog.c delete mode 100644 drivers/staging/isdn/hysdn/hysdn_sched.c delete mode 100644 drivers/staging/isdn/hysdn/ince1pc.h delete mode 100644 include/linux/b1pcmcia.h delete mode 100644 include/uapi/linux/gigaset_dev.h delete mode 100644 include/uapi/linux/hysdn_if.h diff --git a/Documentation/isdn/avmb1.rst b/Documentation/isdn/avmb1.rst deleted file mode 100644 index de3961e67553..000000000000 --- a/Documentation/isdn/avmb1.rst +++ /dev/null @@ -1,246 +0,0 @@ -================================ -Driver for active AVM Controller -================================ - -The driver provides a kernel capi2.0 Interface (kernelcapi) and -on top of this a User-Level-CAPI2.0-interface (capi) -and a driver to connect isdn4linux with CAPI2.0 (capidrv). -The lowlevel interface can be used to implement a CAPI2.0 -also for passive cards since July 1999. - -The author can be reached at calle@calle.in-berlin.de. -The command avmcapictrl is part of the isdn4k-utils. -t4-files can be found at ftp://ftp.avm.de/cardware/b1/linux/firmware - -Currently supported cards: - - - B1 ISA (all versions) - - B1 PCI - - T1/T1B (HEMA card) - - M1 - - M2 - - B1 PCMCIA - -Installing ----------- - -You need at least /dev/capi20 to load the firmware. - -:: - - mknod /dev/capi20 c 68 0 - mknod /dev/capi20.00 c 68 1 - mknod /dev/capi20.01 c 68 2 - . - . - . - mknod /dev/capi20.19 c 68 20 - -Running -------- - -To use the card you need the t4-files to download the firmware. -AVM GmbH provides several t4-files for the different D-channel -protocols (b1.t4 for Euro-ISDN). Install these file in /lib/isdn. - -if you configure as modules load the modules this way:: - - insmod /lib/modules/current/misc/capiutil.o - insmod /lib/modules/current/misc/b1.o - insmod /lib/modules/current/misc/kernelcapi.o - insmod /lib/modules/current/misc/capidrv.o - insmod /lib/modules/current/misc/capi.o - -if you have an B1-PCI card load the module b1pci.o:: - - insmod /lib/modules/current/misc/b1pci.o - -and load the firmware with:: - - avmcapictrl load /lib/isdn/b1.t4 1 - -if you have an B1-ISA card load the module b1isa.o -and add the card by calling:: - - avmcapictrl add 0x150 15 - -and load the firmware by calling:: - - avmcapictrl load /lib/isdn/b1.t4 1 - -if you have an T1-ISA card load the module t1isa.o -and add the card by calling:: - - avmcapictrl add 0x450 15 T1 0 - -and load the firmware by calling:: - - avmcapictrl load /lib/isdn/t1.t4 1 - -if you have an PCMCIA card (B1/M1/M2) load the module b1pcmcia.o -before you insert the card. - -Leased Lines with B1 --------------------- - -Init card and load firmware. - -For an D64S use "FV: 1" as phone number - -For an D64S2 use "FV: 1" and "FV: 2" for multilink -or "FV: 1,2" to use CAPI channel bundling. - -/proc-Interface ------------------ - -/proc/capi:: - - dr-xr-xr-x 2 root root 0 Jul 1 14:03 . - dr-xr-xr-x 82 root root 0 Jun 30 19:08 .. - -r--r--r-- 1 root root 0 Jul 1 14:03 applications - -r--r--r-- 1 root root 0 Jul 1 14:03 applstats - -r--r--r-- 1 root root 0 Jul 1 14:03 capi20 - -r--r--r-- 1 root root 0 Jul 1 14:03 capidrv - -r--r--r-- 1 root root 0 Jul 1 14:03 controller - -r--r--r-- 1 root root 0 Jul 1 14:03 contrstats - -r--r--r-- 1 root root 0 Jul 1 14:03 driver - -r--r--r-- 1 root root 0 Jul 1 14:03 ncci - -r--r--r-- 1 root root 0 Jul 1 14:03 users - -/proc/capi/applications: - applid level3cnt datablkcnt datablklen ncci-cnt recvqueuelen - level3cnt: - capi_register parameter - datablkcnt: - capi_register parameter - ncci-cnt: - current number of nccis (connections) - recvqueuelen: - number of messages on receive queue - - for example:: - - 1 -2 16 2048 1 0 - 2 2 7 2048 1 0 - -/proc/capi/applstats: - applid recvctlmsg nrecvdatamsg nsentctlmsg nsentdatamsg - recvctlmsg: - capi messages received without DATA_B3_IND - recvdatamsg: - capi DATA_B3_IND received - sentctlmsg: - capi messages sent without DATA_B3_REQ - sentdatamsg: - capi DATA_B3_REQ sent - - for example:: - - 1 2057 1699 1721 1699 - -/proc/capi/capi20: statistics of capi.o (/dev/capi20) - minor nopen nrecvdropmsg nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg - minor: - minor device number of capi device - nopen: - number of calls to devices open - nrecvdropmsg: - capi messages dropped (messages in recvqueue in close) - nrecvctlmsg: - capi messages received without DATA_B3_IND - nrecvdatamsg: - capi DATA_B3_IND received - nsentctlmsg: - capi messages sent without DATA_B3_REQ - nsentdatamsg: - capi DATA_B3_REQ sent - - for example:: - - 1 2 18 0 16 2 - -/proc/capi/capidrv: statistics of capidrv.o (capi messages) - nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg - nrecvctlmsg: - capi messages received without DATA_B3_IND - nrecvdatamsg: - capi DATA_B3_IND received - nsentctlmsg: - capi messages sent without DATA_B3_REQ - nsentdatamsg: - capi DATA_B3_REQ sent - - for example: - 2780 2226 2256 2226 - -/proc/capi/controller: - controller drivername state cardname controllerinfo - - for example:: - - 1 b1pci running b1pci-e000 B1 3.07-01 0xe000 19 - 2 t1isa running t1isa-450 B1 3.07-01 0x450 11 0 - 3 b1pcmcia running m2-150 B1 3.07-01 0x150 5 - -/proc/capi/contrstats: - controller nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg - nrecvctlmsg: - capi messages received without DATA_B3_IND - nrecvdatamsg: - capi DATA_B3_IND received - nsentctlmsg: - capi messages sent without DATA_B3_REQ - nsentdatamsg: - capi DATA_B3_REQ sent - - for example:: - - 1 2845 2272 2310 2274 - 2 2 0 2 0 - 3 2 0 2 0 - -/proc/capi/driver: - drivername ncontroller - - for example:: - - b1pci 1 - t1isa 1 - b1pcmcia 1 - b1isa 0 - -/proc/capi/ncci: - apllid ncci winsize sendwindow - - for example:: - - 1 0x10101 8 0 - -/proc/capi/users: kernelmodules that use the kernelcapi. - name - - for example:: - - capidrv - capi20 - -Questions ---------- - -Check out the FAQ (ftp.isdn4linux.de) or subscribe to the -linux-avmb1@calle.in-berlin.de mailing list by sending -a mail to majordomo@calle.in-berlin.de with -subscribe linux-avmb1 -in the body. - -German documentation and several scripts can be found at -ftp://ftp.avm.de/cardware/b1/linux/ - -Bugs ----- - -If you find any please let me know. - -Enjoy, - -Carsten Paeth (calle@calle.in-berlin.de) diff --git a/Documentation/isdn/gigaset.rst b/Documentation/isdn/gigaset.rst deleted file mode 100644 index 98b4ec521c51..000000000000 --- a/Documentation/isdn/gigaset.rst +++ /dev/null @@ -1,465 +0,0 @@ -========================== -GigaSet 307x Device Driver -========================== - -1. Requirements -================= - -1.1. Hardware -------------- - - This driver supports the connection of the Gigaset 307x/417x family of - ISDN DECT bases via Gigaset M101 Data, Gigaset M105 Data or direct USB - connection. The following devices are reported to be compatible: - - Bases: - - Siemens Gigaset 3070/3075 isdn - - Siemens Gigaset 4170/4175 isdn - - Siemens Gigaset SX205/255 - - Siemens Gigaset SX353 - - T-Com Sinus 45 [AB] isdn - - T-Com Sinus 721X[A] [SE] - - Vox Chicago 390 ISDN (KPN Telecom) - - RS232 data boxes: - - Siemens Gigaset M101 Data - - T-Com Sinus 45 Data 1 - - USB data boxes: - - Siemens Gigaset M105 Data - - Siemens Gigaset USB Adapter DECT - - T-Com Sinus 45 Data 2 - - T-Com Sinus 721 data - - Chicago 390 USB (KPN) - - See also http://www.erbze.info/sinus_gigaset.htm - (archived at https://web.archive.org/web/20100717020421/http://www.erbze.info:80/sinus_gigaset.htm ) and - http://gigaset307x.sourceforge.net/ - - We had also reports from users of Gigaset M105 who could use the drivers - with SX 100 and CX 100 ISDN bases (only in unimodem mode, see section 2.5.) - If you have another device that works with our driver, please let us know. - - Chances of getting an USB device to work are good if the output of:: - - lsusb - - at the command line contains one of the following:: - - ID 0681:0001 - ID 0681:0002 - ID 0681:0009 - ID 0681:0021 - ID 0681:0022 - -1.2. Software -------------- - - The driver works with the Kernel CAPI subsystem and can be used with any - software which is able to use CAPI 2.0 for ISDN connections (voice or data). - - There are some user space tools available at - https://sourceforge.net/projects/gigaset307x/ - which provide access to additional device specific functions like SMS, - phonebook or call journal. - - -2. How to use the driver -========================== - -2.1. Modules ------------- - - For the devices to work, the proper kernel modules have to be loaded. - This normally happens automatically when the system detects the USB - device (base, M105) or when the line discipline is attached (M101). It - can also be triggered manually using the modprobe(8) command, for example - for troubleshooting or to pass module parameters. - - The module ser_gigaset provides a serial line discipline N_GIGASET_M101 - which uses the regular serial port driver to access the device, and must - therefore be attached to the serial device to which the M101 is connected. - The ldattach(8) command (included in util-linux-ng release 2.14 or later) - can be used for that purpose, for example:: - - ldattach GIGASET_M101 /dev/ttyS1 - - This will open the device file, attach the line discipline to it, and - then sleep in the background, keeping the device open so that the line - discipline remains active. To deactivate it, kill the daemon, for example - with:: - - killall ldattach - - before disconnecting the device. To have this happen automatically at - system startup/shutdown on an LSB compatible system, create and activate - an appropriate LSB startup script /etc/init.d/gigaset. (The init name - 'gigaset' is officially assigned to this project by LANANA.) - Alternatively, just add the 'ldattach' command line to /etc/rc.local. - - The modules accept the following parameters: - - =============== ========== ========================================== - Module Parameter Meaning - - gigaset debug debug level (see section 3.2.) - - startmode initial operation mode (see section 2.5.): - bas_gigaset ) 1=CAPI (default), 0=Unimodem - ser_gigaset ) - usb_gigaset ) cidmode initial Call-ID mode setting (see section - 2.5.): 1=on (default), 0=off - - =============== ========== ========================================== - - Depending on your distribution you may want to create a separate module - configuration file like /etc/modprobe.d/gigaset.conf for these. - -2.2. Device nodes for user space programs ------------------------------------------ - - The device can be accessed from user space (eg. by the user space tools - mentioned in 1.2.) through the device nodes: - - - /dev/ttyGS0 for M101 (RS232 data boxes) - - /dev/ttyGU0 for M105 (USB data boxes) - - /dev/ttyGB0 for the base driver (direct USB connection) - - If you connect more than one device of a type, they will get consecutive - device nodes, eg. /dev/ttyGU1 for a second M105. - - You can also set a "default device" for the user space tools to use when - no device node is given as parameter, by creating a symlink /dev/ttyG to - one of them, eg.:: - - ln -s /dev/ttyGB0 /dev/ttyG - - The devices accept the following device specific ioctl calls - (defined in gigaset_dev.h): - - ``ioctl(int fd, GIGASET_REDIR, int *cmd);`` - - If cmd==1, the device is set to be controlled exclusively through the - character device node; access from the ISDN subsystem is blocked. - - If cmd==0, the device is set to be used from the ISDN subsystem and does - not communicate through the character device node. - - ``ioctl(int fd, GIGASET_CONFIG, int *cmd);`` - - (ser_gigaset and usb_gigaset only) - - If cmd==1, the device is set to adapter configuration mode where commands - are interpreted by the M10x DECT adapter itself instead of being - forwarded to the base station. In this mode, the device accepts the - commands described in Siemens document "AT-Kommando Alignment M10x Data" - for setting the operation mode, associating with a base station and - querying parameters like field strengh and signal quality. - - Note that there is no ioctl command for leaving adapter configuration - mode and returning to regular operation. In order to leave adapter - configuration mode, write the command ATO to the device. - - ``ioctl(int fd, GIGASET_BRKCHARS, unsigned char brkchars[6]);`` - - (usb_gigaset only) - - Set the break characters on an M105's internal serial adapter to the six - bytes stored in brkchars[]. Unused bytes should be set to zero. - - ioctl(int fd, GIGASET_VERSION, unsigned version[4]); - Retrieve version information from the driver. version[0] must be set to - one of: - - - GIGVER_DRIVER: retrieve driver version - - GIGVER_COMPAT: retrieve interface compatibility version - - GIGVER_FWBASE: retrieve the firmware version of the base - - Upon return, version[] is filled with the requested version information. - -2.3. CAPI ---------- - - The devices will show up as CAPI controllers as soon as the - corresponding driver module is loaded, and can then be used with - CAPI 2.0 kernel and user space applications. For user space access, - the module capi.ko must be loaded. - - Most distributions handle loading and unloading of the various CAPI - modules automatically via the command capiinit(1) from the capi4k-utils - package or a similar mechanism. Note that capiinit(1) cannot unload the - Gigaset drivers because it doesn't support more than one module per - driver. - -2.5. Unimodem mode ------------------- - - In this mode the device works like a modem connected to a serial port - (the /dev/ttyGU0, ... mentioned above) which understands the commands:: - - ATZ init, reset - => OK or ERROR - ATD - ATDT dial - => OK, CONNECT, - BUSY, - NO DIAL TONE, - NO CARRIER, - NO ANSWER - +++ change to command mode when connected - ATH hangup - - You can use some configuration tool of your distribution to configure this - "modem" or configure pppd/wvdial manually. There are some example ppp - configuration files and chat scripts in the gigaset-VERSION/ppp directory - in the driver packages from https://sourceforge.net/projects/gigaset307x/. - Please note that the USB drivers are not able to change the state of the - control lines. This means you must use "Stupid Mode" if you are using - wvdial or you should use the nocrtscts option of pppd. - You must also assure that the ppp_async module is loaded with the parameter - flag_time=0. You can do this e.g. by adding a line like:: - - options ppp_async flag_time=0 - - to an appropriate module configuration file, like:: - - /etc/modprobe.d/gigaset.conf. - - Unimodem mode is needed for making some devices [e.g. SX100] work which - do not support the regular Gigaset command set. If debug output (see - section 3.2.) shows something like this when dialing:: - - CMD Received: ERROR - Available Params: 0 - Connection State: 0, Response: -1 - gigaset_process_response: resp_code -1 in ConState 0 ! - Timeout occurred - - then switching to unimodem mode may help. - - If you have installed the command line tool gigacontr, you can enter - unimodem mode using:: - - gigacontr --mode unimodem - - You can switch back using:: - - gigacontr --mode isdn - - You can also put the driver directly into Unimodem mode when it's loaded, - by passing the module parameter startmode=0 to the hardware specific - module, e.g.:: - - modprobe usb_gigaset startmode=0 - - or by adding a line like:: - - options usb_gigaset startmode=0 - - to an appropriate module configuration file, like:: - - /etc/modprobe.d/gigaset.conf - -2.6. Call-ID (CID) mode ------------------------ - - Call-IDs are numbers used to tag commands to, and responses from, the - Gigaset base in order to support the simultaneous handling of multiple - ISDN calls. Their use can be enabled ("CID mode") or disabled ("Unimodem - mode"). Without Call-IDs (in Unimodem mode), only a very limited set of - functions is available. It allows outgoing data connections only, but - does not signal incoming calls or other base events. - - DECT cordless data devices (M10x) permanently occupy the cordless - connection to the base while Call-IDs are activated. As the Gigaset - bases only support one DECT data connection at a time, this prevents - other DECT cordless data devices from accessing the base. - - During active operation, the driver switches to the necessary mode - automatically. However, for the reasons above, the mode chosen when - the device is not in use (idle) can be selected by the user. - - - If you want to receive incoming calls, you can use the default - settings (CID mode). - - If you have several DECT data devices (M10x) which you want to use - in turn, select Unimodem mode by passing the parameter "cidmode=0" to - the appropriate driver module (ser_gigaset or usb_gigaset). - - If you want both of these at once, you are out of luck. - - You can also use the tty class parameter "cidmode" of the device to - change its CID mode while the driver is loaded, eg.:: - - echo 0 > /sys/class/tty/ttyGU0/cidmode - -2.7. Dialing Numbers --------------------- -provided by an application for dialing out must - be a public network number according to the local dialing plan, without - any dial prefix for getting an outside line. - - Internal calls can be made by providing an internal extension number - prefixed with ``**`` (two asterisks) as the called party number. So to dial - eg. the first registered DECT handset, give ``**11`` as the called party - number. Dialing ``***`` (three asterisks) calls all extensions - simultaneously (global call). - - Unimodem mode does not support internal calls. - -2.8. Unregistered Wireless Devices (M101/M105) ----------------------------------------------- - - The main purpose of the ser_gigaset and usb_gigaset drivers is to allow - the M101 and M105 wireless devices to be used as ISDN devices for ISDN - connections through a Gigaset base. Therefore they assume that the device - is registered to a DECT base. - - If the M101/M105 device is not registered to a base, initialization of - the device fails, and a corresponding error message is logged by the - driver. In that situation, a restricted set of functions is available - which includes, in particular, those necessary for registering the device - to a base or for switching it between Fixed Part and Portable Part - modes. See the gigacontr(8) manpage for details. - -3. Troubleshooting -==================== - -3.1. Solutions to frequently reported problems ----------------------------------------------- - - Problem: - You have a slow provider and isdn4linux gives up dialing too early. - Solution: - Load the isdn module using the dialtimeout option. You can do this e.g. - by adding a line like:: - - options isdn dialtimeout=15 - - to /etc/modprobe.d/gigaset.conf or a similar file. - - Problem: - The isdnlog program emits error messages or just doesn't work. - Solution: - Isdnlog supports only the HiSax driver. Do not attempt to use it with - other drivers such as Gigaset. - - Problem: - You have two or more DECT data adapters (M101/M105) and only the - first one you turn on works. - Solution: - Select Unimodem mode for all DECT data adapters. (see section 2.5.) - - Problem: - Messages like this:: - - usb_gigaset 3-2:1.0: Could not initialize the device. - - appear in your syslog. - Solution: - Check whether your M10x wireless device is correctly registered to the - Gigaset base. (see section 2.7.) - -3.2. Telling the driver to provide more information ---------------------------------------------------- - Building the driver with the "Gigaset debugging" kernel configuration - option (CONFIG_GIGASET_DEBUG) gives it the ability to produce additional - information useful for debugging. - - You can control the amount of debugging information the driver produces by - writing an appropriate value to /sys/module/gigaset/parameters/debug, - e.g.:: - - echo 0 > /sys/module/gigaset/parameters/debug - - switches off debugging output completely, - - :: - - echo 0x302020 > /sys/module/gigaset/parameters/debug - - enables a reasonable set of debugging output messages. These values are - bit patterns where every bit controls a certain type of debugging output. - See the constants DEBUG_* in the source file gigaset.h for details. - - The initial value can be set using the debug parameter when loading the - module "gigaset", e.g. by adding a line:: - - options gigaset debug=0 - - to your module configuration file, eg. /etc/modprobe.d/gigaset.conf - - Generated debugging information can be found - - as output of the command:: - - dmesg - - - in system log files written by your syslog daemon, usually - in /var/log/, e.g. /var/log/messages. - -3.3. Reporting problems and bugs --------------------------------- - If you can't solve problems with the driver on your own, feel free to - use one of the forums, bug trackers, or mailing lists on - - https://sourceforge.net/projects/gigaset307x - - or write an electronic mail to the maintainers. - - Try to provide as much information as possible, such as - - - distribution - - kernel version (uname -r) - - gcc version (gcc --version) - - hardware architecture (uname -m, ...) - - type and firmware version of your device (base and wireless module, - if any) - - output of "lsusb -v" (if using an USB device) - - error messages - - relevant system log messages (it would help if you activate debug - output as described in 3.2.) - - For help with general configuration problems not specific to our driver, - such as isdn4linux and network configuration issues, please refer to the - appropriate forums and newsgroups. - -3.4. Reporting problem solutions --------------------------------- - If you solved a problem with our drivers, wrote startup scripts for your - distribution, ... feel free to contact us (using one of the places - mentioned in 3.3.). We'd like to add scripts, hints, documentation - to the driver and/or the project web page. - - -4. Links, other software -========================== - - - Sourceforge project developing this driver and associated tools - https://sourceforge.net/projects/gigaset307x - - Yahoo! Group on the Siemens Gigaset family of devices - https://de.groups.yahoo.com/group/Siemens-Gigaset - - Siemens Gigaset/T-Sinus compatibility table - http://www.erbze.info/sinus_gigaset.htm - (archived at https://web.archive.org/web/20100717020421/http://www.erbze.info:80/sinus_gigaset.htm ) - - -5. Credits -============ - - Thanks to - - Karsten Keil - for his help with isdn4linux - Deti Fliegl - for his base driver code - Dennis Dietrich - for his kernel 2.6 patches - Andreas Rummel - for his work and logs to get unimodem mode working - Andreas Degert - for his logs and patches to get cx 100 working - Dietrich Feist - for his generous donation of one M105 and two M101 cordless adapters - Christoph Schweers - for his generous donation of a M34 device - - and all the other people who sent logs and other information. diff --git a/Documentation/isdn/hysdn.rst b/Documentation/isdn/hysdn.rst deleted file mode 100644 index 0a168d1cbffc..000000000000 --- a/Documentation/isdn/hysdn.rst +++ /dev/null @@ -1,196 +0,0 @@ -============ -Hysdn Driver -============ - -The hysdn driver has been written by -Werner Cornelius (werner@isdn4linux.de or werner@titro.de) -for Hypercope GmbH Aachen Germany. Hypercope agreed to publish this driver -under the GNU General Public License. - -The CAPI 2.0-support was added by Ulrich Albrecht (ualbrecht@hypercope.de) -for Hypercope GmbH Aachen, Germany. - - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -.. Table of contents - - 1. About the driver - - 2. Loading/Unloading the driver - - 3. Entries in the /proc filesystem - - 4. The /proc/net/hysdn/cardconfX file - - 5. The /proc/net/hysdn/cardlogX file - - 6. Where to get additional info and help - - -1. About the driver -=================== - - The drivers/isdn/hysdn subdir contains a driver for HYPERCOPEs active - PCI isdn cards Champ, Ergo and Metro. To enable support for this cards - enable ISDN support in the kernel config and support for HYSDN cards in - the active cards submenu. The driver may only be compiled and used if - support for loadable modules and the process filesystem have been enabled. - - These cards provide two different interfaces to the kernel. Without the - optional CAPI 2.0 support, they register as ethernet card. IP-routing - to a ISDN-destination is performed on the card itself. All necessary - handlers for various protocols like ppp and others as well as config info - and firmware may be fetched from Hypercopes WWW-Site www.hypercope.de. - - With CAPI 2.0 support enabled, the card can also be used as a CAPI 2.0 - compliant devices with either CAPI 2.0 applications - (check isdn4k-utils) or -using the capidrv module- as a regular - isdn4linux device. This is done via the same mechanism as with the - active AVM cards and in fact uses the same module. - - -2. Loading/Unloading the driver -=============================== - - The module has no command line parameters and auto detects up to 10 cards - in the id-range 0-9. - If a loaded driver shall be unloaded all open files in the /proc/net/hysdn - subdir need to be closed and all ethernet interfaces allocated by this - driver must be shut down. Otherwise the module counter will avoid a module - unload. - - If you are using the CAPI 2.0-interface, make sure to load/modprobe the - kernelcapi-module first. - - If you plan to use the capidrv-link to isdn4linux, make sure to load - capidrv.o after all modules using this driver (i.e. after hysdn and - any avm-specific modules). - -3. Entries in the /proc filesystem -================================== - - When the module has been loaded it adds the directory hysdn in the - /proc/net tree. This directory contains exactly 2 file entries for each - card. One is called cardconfX and the other cardlogX, where X is the - card id number from 0 to 9. - The cards are numbered in the order found in the PCI config data. - -4. The /proc/net/hysdn/cardconfX file -===================================== - - This file may be read to get by everyone to get info about the cards type, - actual state, available features and used resources. - The first 3 entries (id, bus and slot) are PCI info fields, the following - type field gives the information about the cards type: - - - 4 -> Ergo card (server card with 2 b-chans) - - 5 -> Metro card (server card with 4 or 8 b-chans) - - 6 -> Champ card (client card with 2 b-chans) - - The following 3 fields show the hardware assignments for irq, iobase and the - dual ported memory (dp-mem). - - The fields b-chans and fax-chans announce the available card resources of - this types for the user. - - The state variable indicates the actual drivers state for this card with the - following assignments. - - - 0 -> card has not been booted since driver load - - 1 -> card booting is actually in progess - - 2 -> card is in an error state due to a previous boot failure - - 3 -> card is booted and active - - And the last field (device) shows the name of the ethernet device assigned - to this card. Up to the first successful boot this field only shows a - - to tell that no net device has been allocated up to now. Once a net device - has been allocated it remains assigned to this card, even if a card is - rebooted and an boot error occurs. - - Writing to the cardconfX file boots the card or transfers config lines to - the cards firmware. The type of data is automatically detected when the - first data is written. Only root has write access to this file. - The firmware boot files are normally called hyclient.pof for client cards - and hyserver.pof for server cards. - After successfully writing the boot file, complete config files or single - config lines may be copied to this file. - If an error occurs the return value given to the writing process has the - following additional codes (decimal): - - ==== ============================================ - 1000 Another process is currently bootng the card - 1001 Invalid firmware header - 1002 Boards dual-port RAM test failed - 1003 Internal firmware handler error - 1004 Boot image size invalid - 1005 First boot stage (bootstrap loader) failed - 1006 Second boot stage failure - 1007 Timeout waiting for card ready during boot - 1008 Operation only allowed in booted state - 1009 Config line too long - 1010 Invalid channel number - 1011 Timeout sending config data - ==== ============================================ - - Additional info about error reasons may be fetched from the log output. - -5. The /proc/net/hysdn/cardlogX file -==================================== - - The cardlogX file entry may be opened multiple for reading by everyone to - get the cards and drivers log data. Card messages always start with the - keyword LOG. All other lines are output from the driver. - The driver log data may be redirected to the syslog by selecting the - appropriate bitmask. The cards log messages will always be send to this - interface but never to the syslog. - - A root user may write a decimal or hex (with 0x) value t this file to select - desired output options. As mentioned above the cards log dat is always - written to the cardlog file independent of the following options only used - to check and debug the driver itself: - - For example:: - - echo "0x34560078" > /proc/net/hysdn/cardlog0 - - to output the hex log mask 34560078 for card 0. - - The written value is regarded as an unsigned 32-Bit value, bit ored for - desired output. The following bits are already assigned: - - ========== ============================================================ - 0x80000000 All driver log data is alternatively via syslog - 0x00000001 Log memory allocation errors - 0x00000010 Firmware load start and close are logged - 0x00000020 Log firmware record parser - 0x00000040 Log every firmware write actions - 0x00000080 Log all card related boot messages - 0x00000100 Output all config data sent for debugging purposes - 0x00000200 Only non comment config lines are shown wth channel - 0x00000400 Additional conf log output - 0x00001000 Log the asynchronous scheduler actions (config and log) - 0x00100000 Log all open and close actions to /proc/net/hysdn/card files - 0x00200000 Log all actions from /proc file entries - 0x00010000 Log network interface init and deinit - ========== ============================================================ - -6. Where to get additional info and help -======================================== - - If you have any problems concerning the driver or configuration contact - the Hypercope support team (support@hypercope.de) and or the authors - Werner Cornelius (werner@isdn4linux or cornelius@titro.de) or - Ulrich Albrecht (ualbrecht@hypercope.de). diff --git a/Documentation/isdn/index.rst b/Documentation/isdn/index.rst index 407e74b78372..9622939fa526 100644 --- a/Documentation/isdn/index.rst +++ b/Documentation/isdn/index.rst @@ -9,9 +9,6 @@ ISDN interface_capi - avmb1 - gigaset - hysdn m_isdn credits diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 4ef86433bd67..2e91370dc159 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -132,7 +132,6 @@ Code Seq# Include File Comments 'F' 80-8F linux/arcfb.h conflict! 'F' DD video/sstfb.h conflict! 'G' 00-3F drivers/misc/sgi-gru/grulib.h conflict! -'G' 00-0F linux/gigaset_dev.h conflict! 'H' 00-7F linux/hiddev.h conflict! 'H' 00-0F linux/hidraw.h conflict! 'H' 01 linux/mei.h conflict! diff --git a/MAINTAINERS b/MAINTAINERS index bd5847e802de..e53e862bf2c3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8804,7 +8804,7 @@ S: Maintained F: drivers/isdn/mISDN F: drivers/isdn/hardware -ISDN/CAPI SUBSYSTEM +ISDN/CMTP OVER BLUETOOTH M: Karsten Keil L: isdn4linux@listserv.isdn4linux.de (subscribers-only) L: netdev@vger.kernel.org @@ -8812,7 +8812,6 @@ W: http://www.isdn4linux.de S: Odd Fixes F: Documentation/isdn/ F: drivers/isdn/capi/ -F: drivers/staging/isdn/ F: net/bluetooth/cmtp/ F: include/linux/isdn/ F: include/uapi/linux/isdn/ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index eaf753b70ec5..3a334a9dd453 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -116,8 +116,6 @@ source "drivers/staging/fieldbus/Kconfig" source "drivers/staging/kpc2000/Kconfig" -source "drivers/staging/isdn/Kconfig" - source "drivers/staging/wusbcore/Kconfig" source "drivers/staging/uwb/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 0a4396c9067b..fb0c518ce07c 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -48,7 +48,6 @@ obj-$(CONFIG_STAGING_GASKET_FRAMEWORK) += gasket/ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ obj-$(CONFIG_KPC2000) += kpc2000/ -obj-$(CONFIG_ISDN_CAPI) += isdn/ obj-$(CONFIG_UWB) += uwb/ obj-$(CONFIG_USB_WUSB) += wusbcore/ obj-$(CONFIG_EXFAT_FS) += exfat/ diff --git a/drivers/staging/isdn/Kconfig b/drivers/staging/isdn/Kconfig deleted file mode 100644 index faaf63887094..000000000000 --- a/drivers/staging/isdn/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -menu "ISDN CAPI drivers" - depends on ISDN_CAPI - -source "drivers/staging/isdn/avm/Kconfig" - -source "drivers/staging/isdn/gigaset/Kconfig" - -source "drivers/staging/isdn/hysdn/Kconfig" - -endmenu - diff --git a/drivers/staging/isdn/Makefile b/drivers/staging/isdn/Makefile deleted file mode 100644 index 025504bae5df..000000000000 --- a/drivers/staging/isdn/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Makefile for the kernel ISDN subsystem and device drivers. - -# Object files in subdirectories - -obj-$(CONFIG_CAPI_AVM) += avm/ -obj-$(CONFIG_HYSDN) += hysdn/ -obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset/ diff --git a/drivers/staging/isdn/TODO b/drivers/staging/isdn/TODO deleted file mode 100644 index 9210d11eb68b..000000000000 --- a/drivers/staging/isdn/TODO +++ /dev/null @@ -1,22 +0,0 @@ -TODO: Remove in late 2019 unless there are users - - -I tried to find any indication of whether the capi drivers are -still in use, and have not found anything from a long time ago. - -With public ISDN networks almost completely shut down over the past 12 -months, there is very little you can actually do with this hardware. The -main remaining use case would be to connect ISDN voice phones to an -in-house installation with Asterisk or LCR, but anyone trying this in -turn seems to be using either the mISDN driver stack, or out-of-tree -drivers from the hardware vendors. - -I may of course have missed something, so I would suggest moving -these into drivers/staging/ just in case someone still uses one -of the three remaining in-kernel drivers (avm, hysdn, gigaset). - -If nobody complains, we can remove them entirely in six months, -or otherwise move the core code and any drivers that are still -needed back into drivers/isdn. - - Arnd Bergmann diff --git a/drivers/staging/isdn/avm/Kconfig b/drivers/staging/isdn/avm/Kconfig deleted file mode 100644 index 81483db067bb..000000000000 --- a/drivers/staging/isdn/avm/Kconfig +++ /dev/null @@ -1,65 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# ISDN AVM drivers -# - -menuconfig CAPI_AVM - bool "Active AVM cards" - help - Enable support for AVM active ISDN cards. - -if CAPI_AVM - -config ISDN_DRV_AVMB1_B1ISA - tristate "AVM B1 ISA support" - depends on ISA - help - Enable support for the ISA version of the AVM B1 card. - -config ISDN_DRV_AVMB1_B1PCI - tristate "AVM B1 PCI support" - depends on PCI - help - Enable support for the PCI version of the AVM B1 card. - -config ISDN_DRV_AVMB1_B1PCIV4 - bool "AVM B1 PCI V4 support" - depends on ISDN_DRV_AVMB1_B1PCI - help - Enable support for the V4 version of AVM B1 PCI card. - -config ISDN_DRV_AVMB1_T1ISA - tristate "AVM T1/T1-B ISA support" - depends on ISA - help - Enable support for the AVM T1 T1B card. - Note: This is a PRI card and handle 30 B-channels. - -config ISDN_DRV_AVMB1_B1PCMCIA - tristate "AVM B1/M1/M2 PCMCIA support" - depends on PCMCIA - help - Enable support for the PCMCIA version of the AVM B1 card. - -config ISDN_DRV_AVMB1_AVM_CS - tristate "AVM B1/M1/M2 PCMCIA cs module" - depends on ISDN_DRV_AVMB1_B1PCMCIA - help - Enable the PCMCIA client driver for the AVM B1/M1/M2 - PCMCIA cards. - -config ISDN_DRV_AVMB1_T1PCI - tristate "AVM T1/T1-B PCI support" - depends on PCI - help - Enable support for the AVM T1 T1B card. - Note: This is a PRI card and handle 30 B-channels. - -config ISDN_DRV_AVMB1_C4 - tristate "AVM C4/C2 support" - depends on PCI - help - Enable support for the AVM C4/C2 PCI cards. - These cards handle 4/2 BRI ISDN lines (8/4 channels). - -endif # CAPI_AVM diff --git a/drivers/staging/isdn/avm/Makefile b/drivers/staging/isdn/avm/Makefile deleted file mode 100644 index 3830a0573fcc..000000000000 --- a/drivers/staging/isdn/avm/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Makefile for the AVM ISDN device drivers - -# Each configuration option enables a list of files. - -obj-$(CONFIG_ISDN_DRV_AVMB1_B1ISA) += b1isa.o b1.o -obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCI) += b1pci.o b1.o b1dma.o -obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCMCIA) += b1pcmcia.o b1.o -obj-$(CONFIG_ISDN_DRV_AVMB1_AVM_CS) += avm_cs.o -obj-$(CONFIG_ISDN_DRV_AVMB1_T1ISA) += t1isa.o b1.o -obj-$(CONFIG_ISDN_DRV_AVMB1_T1PCI) += t1pci.o b1.o b1dma.o -obj-$(CONFIG_ISDN_DRV_AVMB1_C4) += c4.o b1.o diff --git a/drivers/staging/isdn/avm/avm_cs.c b/drivers/staging/isdn/avm/avm_cs.c deleted file mode 100644 index 62b8030ee331..000000000000 --- a/drivers/staging/isdn/avm/avm_cs.c +++ /dev/null @@ -1,166 +0,0 @@ -/* $Id: avm_cs.c,v 1.4.6.3 2001/09/23 22:24:33 kai Exp $ - * - * A PCMCIA client driver for AVM B1/M1/M2 - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -/*====================================================================*/ - -MODULE_DESCRIPTION("CAPI4Linux: PCMCIA client driver for AVM B1/M1/M2"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/*====================================================================*/ - -static int avmcs_config(struct pcmcia_device *link); -static void avmcs_release(struct pcmcia_device *link); -static void avmcs_detach(struct pcmcia_device *p_dev); - -static int avmcs_probe(struct pcmcia_device *p_dev) -{ - /* General socket configuration */ - p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; - p_dev->config_index = 1; - p_dev->config_regs = PRESENT_OPTION; - - return avmcs_config(p_dev); -} /* avmcs_attach */ - - -static void avmcs_detach(struct pcmcia_device *link) -{ - avmcs_release(link); -} /* avmcs_detach */ - -static int avmcs_configcheck(struct pcmcia_device *p_dev, void *priv_data) -{ - p_dev->resource[0]->end = 16; - p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; - p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - - return pcmcia_request_io(p_dev); -} - -static int avmcs_config(struct pcmcia_device *link) -{ - int i = -1; - char devname[128]; - int cardtype; - int (*addcard)(unsigned int port, unsigned irq); - - devname[0] = 0; - if (link->prod_id[1]) - strlcpy(devname, link->prod_id[1], sizeof(devname)); - - /* - * find IO port - */ - if (pcmcia_loop_config(link, avmcs_configcheck, NULL)) - return -ENODEV; - - do { - if (!link->irq) { - /* undo */ - pcmcia_disable_device(link); - break; - } - - /* - * configure the PCMCIA socket - */ - i = pcmcia_enable_device(link); - if (i != 0) { - pcmcia_disable_device(link); - break; - } - - } while (0); - - if (devname[0]) { - char *s = strrchr(devname, ' '); - if (!s) - s = devname; - else s++; - if (strcmp("M1", s) == 0) { - cardtype = AVM_CARDTYPE_M1; - } else if (strcmp("M2", s) == 0) { - cardtype = AVM_CARDTYPE_M2; - } else { - cardtype = AVM_CARDTYPE_B1; - } - } else - cardtype = AVM_CARDTYPE_B1; - - /* If any step failed, release any partially configured state */ - if (i != 0) { - avmcs_release(link); - return -ENODEV; - } - - - switch (cardtype) { - case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break; - case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break; - default: - case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break; - } - if ((i = (*addcard)(link->resource[0]->start, link->irq)) < 0) { - dev_err(&link->dev, - "avm_cs: failed to add AVM-Controller at i/o %#x, irq %d\n", - (unsigned int) link->resource[0]->start, link->irq); - avmcs_release(link); - return -ENODEV; - } - return 0; - -} /* avmcs_config */ - - -static void avmcs_release(struct pcmcia_device *link) -{ - b1pcmcia_delcard(link->resource[0]->start, link->irq); - pcmcia_disable_device(link); -} /* avmcs_release */ - - -static const struct pcmcia_device_id avmcs_ids[] = { - PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335), - PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M1", 0x95d42008, 0x81e10430), - PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M2", 0x95d42008, 0x18e8558a), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, avmcs_ids); - -static struct pcmcia_driver avmcs_driver = { - .owner = THIS_MODULE, - .name = "avm_cs", - .probe = avmcs_probe, - .remove = avmcs_detach, - .id_table = avmcs_ids, -}; -module_pcmcia_driver(avmcs_driver); diff --git a/drivers/staging/isdn/avm/avmcard.h b/drivers/staging/isdn/avm/avmcard.h deleted file mode 100644 index cdfa89c71997..000000000000 --- a/drivers/staging/isdn/avm/avmcard.h +++ /dev/null @@ -1,581 +0,0 @@ -/* $Id: avmcard.h,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $ - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#ifndef _AVMCARD_H_ -#define _AVMCARD_H_ - -#include -#include -#include - -#define AVMB1_PORTLEN 0x1f -#define AVM_MAXVERSION 8 -#define AVM_NCCI_PER_CHANNEL 4 - -/* - * Versions - */ - -#define VER_DRIVER 0 -#define VER_CARDTYPE 1 -#define VER_HWID 2 -#define VER_SERIAL 3 -#define VER_OPTION 4 -#define VER_PROTO 5 -#define VER_PROFILE 6 -#define VER_CAPI 7 - -enum avmcardtype { - avm_b1isa, - avm_b1pci, - avm_b1pcmcia, - avm_m1, - avm_m2, - avm_t1isa, - avm_t1pci, - avm_c4, - avm_c2 -}; - -typedef struct avmcard_dmabuf { - long size; - u8 *dmabuf; - dma_addr_t dmaaddr; -} avmcard_dmabuf; - -typedef struct avmcard_dmainfo { - u32 recvlen; - avmcard_dmabuf recvbuf; - - avmcard_dmabuf sendbuf; - struct sk_buff_head send_queue; - - struct pci_dev *pcidev; -} avmcard_dmainfo; - -typedef struct avmctrl_info { - char cardname[32]; - - int versionlen; - char versionbuf[1024]; - char *version[AVM_MAXVERSION]; - - char infobuf[128]; /* for function procinfo */ - - struct avmcard *card; - struct capi_ctr capi_ctrl; - - struct list_head ncci_head; -} avmctrl_info; - -typedef struct avmcard { - char name[32]; - - spinlock_t lock; - unsigned int port; - unsigned irq; - unsigned long membase; - enum avmcardtype cardtype; - unsigned char revision; - unsigned char class; - int cardnr; /* for t1isa */ - - char msgbuf[128]; /* capimsg msg part */ - char databuf[2048]; /* capimsg data part */ - - void __iomem *mbase; - volatile u32 csr; - avmcard_dmainfo *dma; - - struct avmctrl_info *ctrlinfo; - - u_int nr_controllers; - u_int nlogcontr; - struct list_head list; -} avmcard; - -extern int b1_irq_table[16]; - -/* - * LLI Messages to the ISDN-ControllerISDN Controller - */ - -#define SEND_POLL 0x72 /* - * after load <- RECEIVE_POLL - */ -#define SEND_INIT 0x11 /* - * first message <- RECEIVE_INIT - * int32 NumApplications int32 - * NumNCCIs int32 BoardNumber - */ -#define SEND_REGISTER 0x12 /* - * register an application int32 - * ApplIDId int32 NumMessages - * int32 NumB3Connections int32 - * NumB3Blocks int32 B3Size - * - * AnzB3Connection != 0 && - * AnzB3Blocks >= 1 && B3Size >= 1 - */ -#define SEND_RELEASE 0x14 /* - * deregister an application int32 - * ApplID - */ -#define SEND_MESSAGE 0x15 /* - * send capi-message int32 length - * capi-data ... - */ -#define SEND_DATA_B3_REQ 0x13 /* - * send capi-data-message int32 - * MsgLength capi-data ... int32 - * B3Length data .... - */ - -#define SEND_CONFIG 0x21 /* - */ - -#define SEND_POLLACK 0x73 /* T1 Watchdog */ - -/* - * LLI Messages from the ISDN-ControllerISDN Controller - */ - -#define RECEIVE_POLL 0x32 /* - * <- after SEND_POLL - */ -#define RECEIVE_INIT 0x27 /* - * <- after SEND_INIT int32 length - * byte total length b1struct board - * driver revision b1struct card - * type b1struct reserved b1struct - * serial number b1struct driver - * capability b1struct d-channel - * protocol b1struct CAPI-2.0 - * profile b1struct capi version - */ -#define RECEIVE_MESSAGE 0x21 /* - * <- after SEND_MESSAGE int32 - * AppllID int32 Length capi-data - * .... - */ -#define RECEIVE_DATA_B3_IND 0x22 /* - * received data int32 AppllID - * int32 Length capi-data ... - * int32 B3Length data ... - */ -#define RECEIVE_START 0x23 /* - * Handshake - */ -#define RECEIVE_STOP 0x24 /* - * Handshake - */ -#define RECEIVE_NEW_NCCI 0x25 /* - * int32 AppllID int32 NCCI int32 - * WindowSize - */ -#define RECEIVE_FREE_NCCI 0x26 /* - * int32 AppllID int32 NCCI - */ -#define RECEIVE_RELEASE 0x26 /* - * int32 AppllID int32 0xffffffff - */ -#define RECEIVE_TASK_READY 0x31 /* - * int32 tasknr - * int32 Length Taskname ... - */ -#define RECEIVE_DEBUGMSG 0x71 /* - * int32 Length message - * - */ -#define RECEIVE_POLLDWORD 0x75 /* t1pci in dword mode */ - -#define WRITE_REGISTER 0x00 -#define READ_REGISTER 0x01 - -/* - * port offsets - */ - -#define B1_READ 0x00 -#define B1_WRITE 0x01 -#define B1_INSTAT 0x02 -#define B1_OUTSTAT 0x03 -#define B1_ANALYSE 0x04 -#define B1_REVISION 0x05 -#define B1_RESET 0x10 - - -#define B1_STAT0(cardtype) ((cardtype) == avm_m1 ? 0x81200000l : 0x80A00000l) -#define B1_STAT1(cardtype) (0x80E00000l) - -/* ---------------------------------------------------------------- */ - -static inline unsigned char b1outp(unsigned int base, - unsigned short offset, - unsigned char value) -{ - outb(value, base + offset); - return inb(base + B1_ANALYSE); -} - - -static inline int b1_rx_full(unsigned int base) -{ - return inb(base + B1_INSTAT) & 0x1; -} - -static inline unsigned char b1_get_byte(unsigned int base) -{ - unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ - while (!b1_rx_full(base) && time_before(jiffies, stop)); - if (b1_rx_full(base)) - return inb(base + B1_READ); - printk(KERN_CRIT "b1lli(0x%x): rx not full after 1 second\n", base); - return 0; -} - -static inline unsigned int b1_get_word(unsigned int base) -{ - unsigned int val = 0; - val |= b1_get_byte(base); - val |= (b1_get_byte(base) << 8); - val |= (b1_get_byte(base) << 16); - val |= (b1_get_byte(base) << 24); - return val; -} - -static inline int b1_tx_empty(unsigned int base) -{ - return inb(base + B1_OUTSTAT) & 0x1; -} - -static inline void b1_put_byte(unsigned int base, unsigned char val) -{ - while (!b1_tx_empty(base)); - b1outp(base, B1_WRITE, val); -} - -static inline int b1_save_put_byte(unsigned int base, unsigned char val) -{ - unsigned long stop = jiffies + 2 * HZ; - while (!b1_tx_empty(base) && time_before(jiffies, stop)); - if (!b1_tx_empty(base)) return -1; - b1outp(base, B1_WRITE, val); - return 0; -} - -static inline void b1_put_word(unsigned int base, unsigned int val) -{ - b1_put_byte(base, val & 0xff); - b1_put_byte(base, (val >> 8) & 0xff); - b1_put_byte(base, (val >> 16) & 0xff); - b1_put_byte(base, (val >> 24) & 0xff); -} - -static inline unsigned int b1_get_slice(unsigned int base, - unsigned char *dp) -{ - unsigned int len, i; - - len = i = b1_get_word(base); - while (i-- > 0) *dp++ = b1_get_byte(base); - return len; -} - -static inline void b1_put_slice(unsigned int base, - unsigned char *dp, unsigned int len) -{ - unsigned i = len; - b1_put_word(base, i); - while (i-- > 0) - b1_put_byte(base, *dp++); -} - -static void b1_wr_reg(unsigned int base, - unsigned int reg, - unsigned int value) -{ - b1_put_byte(base, WRITE_REGISTER); - b1_put_word(base, reg); - b1_put_word(base, value); -} - -static inline unsigned int b1_rd_reg(unsigned int base, - unsigned int reg) -{ - b1_put_byte(base, READ_REGISTER); - b1_put_word(base, reg); - return b1_get_word(base); - -} - -static inline void b1_reset(unsigned int base) -{ - b1outp(base, B1_RESET, 0); - mdelay(55 * 2); /* 2 TIC's */ - - b1outp(base, B1_RESET, 1); - mdelay(55 * 2); /* 2 TIC's */ - - b1outp(base, B1_RESET, 0); - mdelay(55 * 2); /* 2 TIC's */ -} - -static inline unsigned char b1_disable_irq(unsigned int base) -{ - return b1outp(base, B1_INSTAT, 0x00); -} - -/* ---------------------------------------------------------------- */ - -static inline void b1_set_test_bit(unsigned int base, - enum avmcardtype cardtype, - int onoff) -{ - b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20); -} - -static inline int b1_get_test_bit(unsigned int base, - enum avmcardtype cardtype) -{ - return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0; -} - -/* ---------------------------------------------------------------- */ - -#define T1_FASTLINK 0x00 -#define T1_SLOWLINK 0x08 - -#define T1_READ B1_READ -#define T1_WRITE B1_WRITE -#define T1_INSTAT B1_INSTAT -#define T1_OUTSTAT B1_OUTSTAT -#define T1_IRQENABLE 0x05 -#define T1_FIFOSTAT 0x06 -#define T1_RESETLINK 0x10 -#define T1_ANALYSE 0x11 -#define T1_IRQMASTER 0x12 -#define T1_IDENT 0x17 -#define T1_RESETBOARD 0x1f - -#define T1F_IREADY 0x01 -#define T1F_IHALF 0x02 -#define T1F_IFULL 0x04 -#define T1F_IEMPTY 0x08 -#define T1F_IFLAGS 0xF0 - -#define T1F_OREADY 0x10 -#define T1F_OHALF 0x20 -#define T1F_OEMPTY 0x40 -#define T1F_OFULL 0x80 -#define T1F_OFLAGS 0xF0 - -/* there are HEMA cards with 1k and 4k FIFO out */ -#define FIFO_OUTBSIZE 256 -#define FIFO_INPBSIZE 512 - -#define HEMA_VERSION_ID 0 -#define HEMA_PAL_ID 0 - -static inline void t1outp(unsigned int base, - unsigned short offset, - unsigned char value) -{ - outb(value, base + offset); -} - -static inline unsigned char t1inp(unsigned int base, - unsigned short offset) -{ - return inb(base + offset); -} - -static inline int t1_isfastlink(unsigned int base) -{ - return (inb(base + T1_IDENT) & ~0x82) == 1; -} - -static inline unsigned char t1_fifostatus(unsigned int base) -{ - return inb(base + T1_FIFOSTAT); -} - -static inline unsigned int t1_get_slice(unsigned int base, - unsigned char *dp) -{ - unsigned int len, i; -#ifdef FASTLINK_DEBUG - unsigned wcnt = 0, bcnt = 0; -#endif - - len = i = b1_get_word(base); - if (t1_isfastlink(base)) { - int status; - while (i > 0) { - status = t1_fifostatus(base) & (T1F_IREADY | T1F_IHALF); - if (i >= FIFO_INPBSIZE) status |= T1F_IFULL; - - switch (status) { - case T1F_IREADY | T1F_IHALF | T1F_IFULL: - insb(base + B1_READ, dp, FIFO_INPBSIZE); - dp += FIFO_INPBSIZE; - i -= FIFO_INPBSIZE; -#ifdef FASTLINK_DEBUG - wcnt += FIFO_INPBSIZE; -#endif - break; - case T1F_IREADY | T1F_IHALF: - insb(base + B1_READ, dp, i); -#ifdef FASTLINK_DEBUG - wcnt += i; -#endif - dp += i; - i = 0; - break; - default: - *dp++ = b1_get_byte(base); - i--; -#ifdef FASTLINK_DEBUG - bcnt++; -#endif - break; - } - } -#ifdef FASTLINK_DEBUG - if (wcnt) - printk(KERN_DEBUG "b1lli(0x%x): get_slice l=%d w=%d b=%d\n", - base, len, wcnt, bcnt); -#endif - } else { - while (i-- > 0) - *dp++ = b1_get_byte(base); - } - return len; -} - -static inline void t1_put_slice(unsigned int base, - unsigned char *dp, unsigned int len) -{ - unsigned i = len; - b1_put_word(base, i); - if (t1_isfastlink(base)) { - int status; - while (i > 0) { - status = t1_fifostatus(base) & (T1F_OREADY | T1F_OHALF); - if (i >= FIFO_OUTBSIZE) status |= T1F_OEMPTY; - switch (status) { - case T1F_OREADY | T1F_OHALF | T1F_OEMPTY: - outsb(base + B1_WRITE, dp, FIFO_OUTBSIZE); - dp += FIFO_OUTBSIZE; - i -= FIFO_OUTBSIZE; - break; - case T1F_OREADY | T1F_OHALF: - outsb(base + B1_WRITE, dp, i); - dp += i; - i = 0; - break; - default: - b1_put_byte(base, *dp++); - i--; - break; - } - } - } else { - while (i-- > 0) - b1_put_byte(base, *dp++); - } -} - -static inline void t1_disable_irq(unsigned int base) -{ - t1outp(base, T1_IRQMASTER, 0x00); -} - -static inline void t1_reset(unsigned int base) -{ - /* reset T1 Controller */ - b1_reset(base); - /* disable irq on HEMA */ - t1outp(base, B1_INSTAT, 0x00); - t1outp(base, B1_OUTSTAT, 0x00); - t1outp(base, T1_IRQMASTER, 0x00); - /* reset HEMA board configuration */ - t1outp(base, T1_RESETBOARD, 0xf); -} - -static inline void b1_setinterrupt(unsigned int base, unsigned irq, - enum avmcardtype cardtype) -{ - switch (cardtype) { - case avm_t1isa: - t1outp(base, B1_INSTAT, 0x00); - t1outp(base, B1_INSTAT, 0x02); - t1outp(base, T1_IRQMASTER, 0x08); - break; - case avm_b1isa: - b1outp(base, B1_INSTAT, 0x00); - b1outp(base, B1_RESET, b1_irq_table[irq]); - b1outp(base, B1_INSTAT, 0x02); - break; - default: - case avm_m1: - case avm_m2: - case avm_b1pci: - b1outp(base, B1_INSTAT, 0x00); - b1outp(base, B1_RESET, 0xf0); - b1outp(base, B1_INSTAT, 0x02); - break; - case avm_c4: - case avm_t1pci: - b1outp(base, B1_RESET, 0xf0); - break; - } -} - -/* b1.c */ -avmcard *b1_alloc_card(int nr_controllers); -void b1_free_card(avmcard *card); -int b1_detect(unsigned int base, enum avmcardtype cardtype); -void b1_getrevision(avmcard *card); -int b1_load_t4file(avmcard *card, capiloaddatapart *t4file); -int b1_load_config(avmcard *card, capiloaddatapart *config); -int b1_loaded(avmcard *card); - -int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data); -void b1_reset_ctr(struct capi_ctr *ctrl); -void b1_register_appl(struct capi_ctr *ctrl, u16 appl, - capi_register_params *rp); -void b1_release_appl(struct capi_ctr *ctrl, u16 appl); -u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); -void b1_parse_version(avmctrl_info *card); -irqreturn_t b1_interrupt(int interrupt, void *devptr); - -int b1_proc_show(struct seq_file *m, void *v); - -avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *, - long rsize, long ssize); -void avmcard_dma_free(avmcard_dmainfo *); - -/* b1dma.c */ -int b1pciv4_detect(avmcard *card); -int t1pci_detect(avmcard *card); -void b1dma_reset(avmcard *card); -irqreturn_t b1dma_interrupt(int interrupt, void *devptr); - -int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data); -void b1dma_reset_ctr(struct capi_ctr *ctrl); -void b1dma_remove_ctr(struct capi_ctr *ctrl); -void b1dma_register_appl(struct capi_ctr *ctrl, - u16 appl, - capi_register_params *rp); -void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl); -u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); -int b1dma_proc_show(struct seq_file *m, void *v); - -#endif /* _AVMCARD_H_ */ diff --git a/drivers/staging/isdn/avm/b1.c b/drivers/staging/isdn/avm/b1.c deleted file mode 100644 index 32ec8cf31fd0..000000000000 --- a/drivers/staging/isdn/avm/b1.c +++ /dev/null @@ -1,819 +0,0 @@ -/* $Id: b1.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ - * - * Common module for AVM B1 cards. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" -#include -#include - -static char *revision = "$Revision: 1.1.2.2 $"; - -/* ------------------------------------------------------------- */ - -MODULE_DESCRIPTION("CAPI4Linux: Common support for active AVM cards"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------- */ - -int b1_irq_table[16] = -{0, - 0, - 0, - 192, /* irq 3 */ - 32, /* irq 4 */ - 160, /* irq 5 */ - 96, /* irq 6 */ - 224, /* irq 7 */ - 0, - 64, /* irq 9 */ - 80, /* irq 10 */ - 208, /* irq 11 */ - 48, /* irq 12 */ - 0, - 0, - 112, /* irq 15 */ -}; - -/* ------------------------------------------------------------- */ - -avmcard *b1_alloc_card(int nr_controllers) -{ - avmcard *card; - avmctrl_info *cinfo; - int i; - - card = kzalloc(sizeof(*card), GFP_KERNEL); - if (!card) - return NULL; - - cinfo = kcalloc(nr_controllers, sizeof(*cinfo), GFP_KERNEL); - if (!cinfo) { - kfree(card); - return NULL; - } - - card->ctrlinfo = cinfo; - for (i = 0; i < nr_controllers; i++) { - INIT_LIST_HEAD(&cinfo[i].ncci_head); - cinfo[i].card = card; - } - spin_lock_init(&card->lock); - card->nr_controllers = nr_controllers; - - return card; -} - -/* ------------------------------------------------------------- */ - -void b1_free_card(avmcard *card) -{ - kfree(card->ctrlinfo); - kfree(card); -} - -/* ------------------------------------------------------------- */ - -int b1_detect(unsigned int base, enum avmcardtype cardtype) -{ - int onoff, i; - - /* - * Statusregister 0000 00xx - */ - if ((inb(base + B1_INSTAT) & 0xfc) - || (inb(base + B1_OUTSTAT) & 0xfc)) - return 1; - /* - * Statusregister 0000 001x - */ - b1outp(base, B1_INSTAT, 0x2); /* enable irq */ - /* b1outp(base, B1_OUTSTAT, 0x2); */ - if ((inb(base + B1_INSTAT) & 0xfe) != 0x2 - /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */) - return 2; - /* - * Statusregister 0000 000x - */ - b1outp(base, B1_INSTAT, 0x0); /* disable irq */ - b1outp(base, B1_OUTSTAT, 0x0); - if ((inb(base + B1_INSTAT) & 0xfe) - || (inb(base + B1_OUTSTAT) & 0xfe)) - return 3; - - for (onoff = !0, i = 0; i < 10; i++) { - b1_set_test_bit(base, cardtype, onoff); - if (b1_get_test_bit(base, cardtype) != onoff) - return 4; - onoff = !onoff; - } - - if (cardtype == avm_m1) - return 0; - - if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01) - return 5; - - return 0; -} - -void b1_getrevision(avmcard *card) -{ - card->class = inb(card->port + B1_ANALYSE); - card->revision = inb(card->port + B1_REVISION); -} - -#define FWBUF_SIZE 256 -int b1_load_t4file(avmcard *card, capiloaddatapart *t4file) -{ - unsigned char buf[FWBUF_SIZE]; - unsigned char *dp; - int i, left; - unsigned int base = card->port; - - dp = t4file->data; - left = t4file->len; - while (left > FWBUF_SIZE) { - if (t4file->user) { - if (copy_from_user(buf, dp, FWBUF_SIZE)) - return -EFAULT; - } else { - memcpy(buf, dp, FWBUF_SIZE); - } - for (i = 0; i < FWBUF_SIZE; i++) - if (b1_save_put_byte(base, buf[i]) < 0) { - printk(KERN_ERR "%s: corrupted firmware file ?\n", - card->name); - return -EIO; - } - left -= FWBUF_SIZE; - dp += FWBUF_SIZE; - } - if (left) { - if (t4file->user) { - if (copy_from_user(buf, dp, left)) - return -EFAULT; - } else { - memcpy(buf, dp, left); - } - for (i = 0; i < left; i++) - if (b1_save_put_byte(base, buf[i]) < 0) { - printk(KERN_ERR "%s: corrupted firmware file ?\n", - card->name); - return -EIO; - } - } - return 0; -} - -int b1_load_config(avmcard *card, capiloaddatapart *config) -{ - unsigned char buf[FWBUF_SIZE]; - unsigned char *dp; - unsigned int base = card->port; - int i, j, left; - - dp = config->data; - left = config->len; - if (left) { - b1_put_byte(base, SEND_CONFIG); - b1_put_word(base, 1); - b1_put_byte(base, SEND_CONFIG); - b1_put_word(base, left); - } - while (left > FWBUF_SIZE) { - if (config->user) { - if (copy_from_user(buf, dp, FWBUF_SIZE)) - return -EFAULT; - } else { - memcpy(buf, dp, FWBUF_SIZE); - } - for (i = 0; i < FWBUF_SIZE; ) { - b1_put_byte(base, SEND_CONFIG); - for (j = 0; j < 4; j++) { - b1_put_byte(base, buf[i++]); - } - } - left -= FWBUF_SIZE; - dp += FWBUF_SIZE; - } - if (left) { - if (config->user) { - if (copy_from_user(buf, dp, left)) - return -EFAULT; - } else { - memcpy(buf, dp, left); - } - for (i = 0; i < left; ) { - b1_put_byte(base, SEND_CONFIG); - for (j = 0; j < 4; j++) { - if (i < left) - b1_put_byte(base, buf[i++]); - else - b1_put_byte(base, 0); - } - } - } - return 0; -} - -int b1_loaded(avmcard *card) -{ - unsigned int base = card->port; - unsigned long stop; - unsigned char ans; - unsigned long tout = 2; - - for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { - if (b1_tx_empty(base)) - break; - } - if (!b1_tx_empty(base)) { - printk(KERN_ERR "%s: b1_loaded: tx err, corrupted t4 file ?\n", - card->name); - return 0; - } - b1_put_byte(base, SEND_POLL); - for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { - if (b1_rx_full(base)) { - ans = b1_get_byte(base); - if (ans == RECEIVE_POLL) - return 1; - - printk(KERN_ERR "%s: b1_loaded: got 0x%x, firmware not running\n", - card->name, ans); - return 0; - } - } - printk(KERN_ERR "%s: b1_loaded: firmware not running\n", card->name); - return 0; -} - -/* ------------------------------------------------------------- */ - -int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - int retval; - - b1_reset(port); - retval = b1_load_t4file(card, &data->firmware); - - if (retval) { - b1_reset(port); - printk(KERN_ERR "%s: failed to load t4file!!\n", - card->name); - return retval; - } - - b1_disable_irq(port); - - if (data->configuration.len > 0 && data->configuration.data) { - retval = b1_load_config(card, &data->configuration); - if (retval) { - b1_reset(port); - printk(KERN_ERR "%s: failed to load config!!\n", - card->name); - return retval; - } - } - - if (!b1_loaded(card)) { - printk(KERN_ERR "%s: failed to load t4file.\n", card->name); - return -EIO; - } - - spin_lock_irqsave(&card->lock, flags); - b1_setinterrupt(port, card->irq, card->cardtype); - b1_put_byte(port, SEND_INIT); - b1_put_word(port, CAPI_MAXAPPL); - b1_put_word(port, AVM_NCCI_PER_CHANNEL * 2); - b1_put_word(port, ctrl->cnr - 1); - spin_unlock_irqrestore(&card->lock, flags); - - return 0; -} - -void b1_reset_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - - b1_reset(port); - b1_reset(port); - - memset(cinfo->version, 0, sizeof(cinfo->version)); - spin_lock_irqsave(&card->lock, flags); - capilib_release(&cinfo->ncci_head); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_down(ctrl); -} - -void b1_register_appl(struct capi_ctr *ctrl, - u16 appl, - capi_register_params *rp) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - int nconn, want = rp->level3cnt; - - if (want > 0) nconn = want; - else nconn = ctrl->profile.nbchannel * -want; - if (nconn == 0) nconn = ctrl->profile.nbchannel; - - spin_lock_irqsave(&card->lock, flags); - b1_put_byte(port, SEND_REGISTER); - b1_put_word(port, appl); - b1_put_word(port, 1024 * (nconn + 1)); - b1_put_word(port, nconn); - b1_put_word(port, rp->datablkcnt); - b1_put_word(port, rp->datablklen); - spin_unlock_irqrestore(&card->lock, flags); -} - -void b1_release_appl(struct capi_ctr *ctrl, u16 appl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - capilib_release_appl(&cinfo->ncci_head, appl); - b1_put_byte(port, SEND_RELEASE); - b1_put_word(port, appl); - spin_unlock_irqrestore(&card->lock, flags); -} - -u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - u16 len = CAPIMSG_LEN(skb->data); - u8 cmd = CAPIMSG_COMMAND(skb->data); - u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data); - u16 dlen, retval; - - spin_lock_irqsave(&card->lock, flags); - if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { - retval = capilib_data_b3_req(&cinfo->ncci_head, - CAPIMSG_APPID(skb->data), - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - if (retval != CAPI_NOERROR) { - spin_unlock_irqrestore(&card->lock, flags); - return retval; - } - - dlen = CAPIMSG_DATALEN(skb->data); - - b1_put_byte(port, SEND_DATA_B3_REQ); - b1_put_slice(port, skb->data, len); - b1_put_slice(port, skb->data + len, dlen); - } else { - b1_put_byte(port, SEND_MESSAGE); - b1_put_slice(port, skb->data, len); - } - spin_unlock_irqrestore(&card->lock, flags); - - dev_kfree_skb_any(skb); - return CAPI_NOERROR; -} - -/* ------------------------------------------------------------- */ - -void b1_parse_version(avmctrl_info *cinfo) -{ - struct capi_ctr *ctrl = &cinfo->capi_ctrl; - avmcard *card = cinfo->card; - capi_profile *profp; - u8 *dversion; - u8 flag; - int i, j; - - for (j = 0; j < AVM_MAXVERSION; j++) - cinfo->version[j] = ""; - for (i = 0, j = 0; - j < AVM_MAXVERSION && i < cinfo->versionlen; - j++, i += cinfo->versionbuf[i] + 1) - cinfo->version[j] = &cinfo->versionbuf[i + 1]; - - strlcpy(ctrl->serial, cinfo->version[VER_SERIAL], sizeof(ctrl->serial)); - memcpy(&ctrl->profile, cinfo->version[VER_PROFILE], sizeof(capi_profile)); - strlcpy(ctrl->manu, "AVM GmbH", sizeof(ctrl->manu)); - dversion = cinfo->version[VER_DRIVER]; - ctrl->version.majorversion = 2; - ctrl->version.minorversion = 0; - ctrl->version.majormanuversion = (((dversion[0] - '0') & 0xf) << 4); - ctrl->version.majormanuversion |= ((dversion[2] - '0') & 0xf); - ctrl->version.minormanuversion = (dversion[3] - '0') << 4; - ctrl->version.minormanuversion |= - (dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf); - - profp = &ctrl->profile; - - flag = ((u8 *)(profp->manu))[1]; - switch (flag) { - case 0: if (cinfo->version[VER_CARDTYPE]) - strcpy(cinfo->cardname, cinfo->version[VER_CARDTYPE]); - else strcpy(cinfo->cardname, "B1"); - break; - case 3: strcpy(cinfo->cardname, "PCMCIA B"); break; - case 4: strcpy(cinfo->cardname, "PCMCIA M1"); break; - case 5: strcpy(cinfo->cardname, "PCMCIA M2"); break; - case 6: strcpy(cinfo->cardname, "B1 V3.0"); break; - case 7: strcpy(cinfo->cardname, "B1 PCI"); break; - default: sprintf(cinfo->cardname, "AVM?%u", (unsigned int)flag); break; - } - printk(KERN_NOTICE "%s: card %d \"%s\" ready.\n", - card->name, ctrl->cnr, cinfo->cardname); - - flag = ((u8 *)(profp->manu))[3]; - if (flag) - printk(KERN_NOTICE "%s: card %d Protocol:%s%s%s%s%s%s%s\n", - card->name, - ctrl->cnr, - (flag & 0x01) ? " DSS1" : "", - (flag & 0x02) ? " CT1" : "", - (flag & 0x04) ? " VN3" : "", - (flag & 0x08) ? " NI1" : "", - (flag & 0x10) ? " AUSTEL" : "", - (flag & 0x20) ? " ESS" : "", - (flag & 0x40) ? " 1TR6" : "" - ); - - flag = ((u8 *)(profp->manu))[5]; - if (flag) - printk(KERN_NOTICE "%s: card %d Linetype:%s%s%s%s\n", - card->name, - ctrl->cnr, - (flag & 0x01) ? " point to point" : "", - (flag & 0x02) ? " point to multipoint" : "", - (flag & 0x08) ? " leased line without D-channel" : "", - (flag & 0x04) ? " leased line with D-channel" : "" - ); -} - -/* ------------------------------------------------------------- */ - -irqreturn_t b1_interrupt(int interrupt, void *devptr) -{ - avmcard *card = devptr; - avmctrl_info *cinfo = &card->ctrlinfo[0]; - struct capi_ctr *ctrl = &cinfo->capi_ctrl; - unsigned char b1cmd; - struct sk_buff *skb; - - unsigned ApplId; - unsigned MsgLen; - unsigned DataB3Len; - unsigned NCCI; - unsigned WindowSize; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - - if (!b1_rx_full(card->port)) { - spin_unlock_irqrestore(&card->lock, flags); - return IRQ_NONE; - } - - b1cmd = b1_get_byte(card->port); - - switch (b1cmd) { - - case RECEIVE_DATA_B3_IND: - - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = b1_get_slice(card->port, card->msgbuf); - DataB3Len = b1_get_slice(card->port, card->databuf); - spin_unlock_irqrestore(&card->lock, flags); - - if (MsgLen < 30) { /* not CAPI 64Bit */ - memset(card->msgbuf + MsgLen, 0, 30-MsgLen); - MsgLen = 30; - CAPIMSG_SETLEN(card->msgbuf, 30); - } - - skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC); - if (!skb) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - skb_put_data(skb, card->databuf, DataB3Len); - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_MESSAGE: - - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = b1_get_slice(card->port, card->msgbuf); - skb = alloc_skb(MsgLen, GFP_ATOMIC); - - if (!skb) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - spin_unlock_irqrestore(&card->lock, flags); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF) - capilib_data_b3_conf(&cinfo->ncci_head, ApplId, - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_NEW_NCCI: - - ApplId = b1_get_word(card->port); - NCCI = b1_get_word(card->port); - WindowSize = b1_get_word(card->port); - capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize); - spin_unlock_irqrestore(&card->lock, flags); - break; - - case RECEIVE_FREE_NCCI: - - ApplId = b1_get_word(card->port); - NCCI = b1_get_word(card->port); - if (NCCI != 0xffffffff) - capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI); - spin_unlock_irqrestore(&card->lock, flags); - break; - - case RECEIVE_START: - /* b1_put_byte(card->port, SEND_POLLACK); */ - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_resume_output(ctrl); - break; - - case RECEIVE_STOP: - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_suspend_output(ctrl); - break; - - case RECEIVE_INIT: - - cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf); - spin_unlock_irqrestore(&card->lock, flags); - b1_parse_version(cinfo); - printk(KERN_INFO "%s: %s-card (%s) now active\n", - card->name, - cinfo->version[VER_CARDTYPE], - cinfo->version[VER_DRIVER]); - capi_ctr_ready(ctrl); - break; - - case RECEIVE_TASK_READY: - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = b1_get_slice(card->port, card->msgbuf); - spin_unlock_irqrestore(&card->lock, flags); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: task %d \"%s\" ready.\n", - card->name, ApplId, card->msgbuf); - break; - - case RECEIVE_DEBUGMSG: - MsgLen = b1_get_slice(card->port, card->msgbuf); - spin_unlock_irqrestore(&card->lock, flags); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); - break; - - case 0xff: - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_ERR "%s: card removed ?\n", card->name); - return IRQ_NONE; - default: - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n", - card->name, b1cmd); - return IRQ_HANDLED; - } - return IRQ_HANDLED; -} - -/* ------------------------------------------------------------- */ -int b1_proc_show(struct seq_file *m, void *v) -{ - struct capi_ctr *ctrl = m->private; - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - u8 flag; - char *s; - - seq_printf(m, "%-16s %s\n", "name", card->name); - seq_printf(m, "%-16s 0x%x\n", "io", card->port); - seq_printf(m, "%-16s %d\n", "irq", card->irq); - switch (card->cardtype) { - case avm_b1isa: s = "B1 ISA"; break; - case avm_b1pci: s = "B1 PCI"; break; - case avm_b1pcmcia: s = "B1 PCMCIA"; break; - case avm_m1: s = "M1"; break; - case avm_m2: s = "M2"; break; - case avm_t1isa: s = "T1 ISA (HEMA)"; break; - case avm_t1pci: s = "T1 PCI"; break; - case avm_c4: s = "C4"; break; - case avm_c2: s = "C2"; break; - default: s = "???"; break; - } - seq_printf(m, "%-16s %s\n", "type", s); - if (card->cardtype == avm_t1isa) - seq_printf(m, "%-16s %d\n", "cardnr", card->cardnr); - - s = cinfo->version[VER_DRIVER]; - if (s) - seq_printf(m, "%-16s %s\n", "ver_driver", s); - - s = cinfo->version[VER_CARDTYPE]; - if (s) - seq_printf(m, "%-16s %s\n", "ver_cardtype", s); - - s = cinfo->version[VER_SERIAL]; - if (s) - seq_printf(m, "%-16s %s\n", "ver_serial", s); - - if (card->cardtype != avm_m1) { - flag = ((u8 *)(ctrl->profile.manu))[3]; - if (flag) - seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", - "protocol", - (flag & 0x01) ? " DSS1" : "", - (flag & 0x02) ? " CT1" : "", - (flag & 0x04) ? " VN3" : "", - (flag & 0x08) ? " NI1" : "", - (flag & 0x10) ? " AUSTEL" : "", - (flag & 0x20) ? " ESS" : "", - (flag & 0x40) ? " 1TR6" : "" - ); - } - if (card->cardtype != avm_m1) { - flag = ((u8 *)(ctrl->profile.manu))[5]; - if (flag) - seq_printf(m, "%-16s%s%s%s%s\n", - "linetype", - (flag & 0x01) ? " point to point" : "", - (flag & 0x02) ? " point to multipoint" : "", - (flag & 0x08) ? " leased line without D-channel" : "", - (flag & 0x04) ? " leased line with D-channel" : "" - ); - } - seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); - - return 0; -} -EXPORT_SYMBOL(b1_proc_show); - -/* ------------------------------------------------------------- */ - -#ifdef CONFIG_PCI - -avmcard_dmainfo * -avmcard_dma_alloc(char *name, struct pci_dev *pdev, long rsize, long ssize) -{ - avmcard_dmainfo *p; - void *buf; - - p = kzalloc(sizeof(avmcard_dmainfo), GFP_KERNEL); - if (!p) { - printk(KERN_WARNING "%s: no memory.\n", name); - goto err; - } - - p->recvbuf.size = rsize; - buf = pci_alloc_consistent(pdev, rsize, &p->recvbuf.dmaaddr); - if (!buf) { - printk(KERN_WARNING "%s: allocation of receive dma buffer failed.\n", name); - goto err_kfree; - } - p->recvbuf.dmabuf = buf; - - p->sendbuf.size = ssize; - buf = pci_alloc_consistent(pdev, ssize, &p->sendbuf.dmaaddr); - if (!buf) { - printk(KERN_WARNING "%s: allocation of send dma buffer failed.\n", name); - goto err_free_consistent; - } - - p->sendbuf.dmabuf = buf; - skb_queue_head_init(&p->send_queue); - - return p; - -err_free_consistent: - pci_free_consistent(p->pcidev, p->recvbuf.size, - p->recvbuf.dmabuf, p->recvbuf.dmaaddr); -err_kfree: - kfree(p); -err: - return NULL; -} - -void avmcard_dma_free(avmcard_dmainfo *p) -{ - pci_free_consistent(p->pcidev, p->recvbuf.size, - p->recvbuf.dmabuf, p->recvbuf.dmaaddr); - pci_free_consistent(p->pcidev, p->sendbuf.size, - p->sendbuf.dmabuf, p->sendbuf.dmaaddr); - skb_queue_purge(&p->send_queue); - kfree(p); -} - -EXPORT_SYMBOL(avmcard_dma_alloc); -EXPORT_SYMBOL(avmcard_dma_free); - -#endif - -EXPORT_SYMBOL(b1_irq_table); - -EXPORT_SYMBOL(b1_alloc_card); -EXPORT_SYMBOL(b1_free_card); -EXPORT_SYMBOL(b1_detect); -EXPORT_SYMBOL(b1_getrevision); -EXPORT_SYMBOL(b1_load_t4file); -EXPORT_SYMBOL(b1_load_config); -EXPORT_SYMBOL(b1_loaded); -EXPORT_SYMBOL(b1_load_firmware); -EXPORT_SYMBOL(b1_reset_ctr); -EXPORT_SYMBOL(b1_register_appl); -EXPORT_SYMBOL(b1_release_appl); -EXPORT_SYMBOL(b1_send_message); - -EXPORT_SYMBOL(b1_parse_version); -EXPORT_SYMBOL(b1_interrupt); - -static int __init b1_init(void) -{ - char *p; - char rev[32]; - - p = strchr(revision, ':'); - if (p && p[1]) { - strlcpy(rev, p + 2, 32); - p = strchr(rev, '$'); - if (p && p > rev) - *(p - 1) = 0; - } else { - strcpy(rev, "1.0"); - } - printk(KERN_INFO "b1: revision %s\n", rev); - - return 0; -} - -static void __exit b1_exit(void) -{ -} - -module_init(b1_init); -module_exit(b1_exit); diff --git a/drivers/staging/isdn/avm/b1dma.c b/drivers/staging/isdn/avm/b1dma.c deleted file mode 100644 index 6a3dc9937ce5..000000000000 --- a/drivers/staging/isdn/avm/b1dma.c +++ /dev/null @@ -1,981 +0,0 @@ -/* $Id: b1dma.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $ - * - * Common module for AVM B1 cards that support dma with AMCC - * - * Copyright 2000 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" -#include -#include - -static char *revision = "$Revision: 1.1.2.3 $"; - -#undef AVM_B1DMA_DEBUG - -/* ------------------------------------------------------------- */ - -MODULE_DESCRIPTION("CAPI4Linux: DMA support for active AVM cards"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -static bool suppress_pollack = 0; -module_param(suppress_pollack, bool, 0); - -/* ------------------------------------------------------------- */ - -static void b1dma_dispatch_tx(avmcard *card); - -/* ------------------------------------------------------------- */ - -/* S5933 */ - -#define AMCC_RXPTR 0x24 -#define AMCC_RXLEN 0x28 -#define AMCC_TXPTR 0x2c -#define AMCC_TXLEN 0x30 - -#define AMCC_INTCSR 0x38 -# define EN_READ_TC_INT 0x00008000L -# define EN_WRITE_TC_INT 0x00004000L -# define EN_TX_TC_INT EN_READ_TC_INT -# define EN_RX_TC_INT EN_WRITE_TC_INT -# define AVM_FLAG 0x30000000L - -# define ANY_S5933_INT 0x00800000L -# define READ_TC_INT 0x00080000L -# define WRITE_TC_INT 0x00040000L -# define TX_TC_INT READ_TC_INT -# define RX_TC_INT WRITE_TC_INT -# define MASTER_ABORT_INT 0x00100000L -# define TARGET_ABORT_INT 0x00200000L -# define BUS_MASTER_INT 0x00200000L -# define ALL_INT 0x000C0000L - -#define AMCC_MCSR 0x3c -# define A2P_HI_PRIORITY 0x00000100L -# define EN_A2P_TRANSFERS 0x00000400L -# define P2A_HI_PRIORITY 0x00001000L -# define EN_P2A_TRANSFERS 0x00004000L -# define RESET_A2P_FLAGS 0x04000000L -# define RESET_P2A_FLAGS 0x02000000L - -/* ------------------------------------------------------------- */ - -static inline void b1dma_writel(avmcard *card, u32 value, int off) -{ - writel(value, card->mbase + off); -} - -static inline u32 b1dma_readl(avmcard *card, int off) -{ - return readl(card->mbase + off); -} - -/* ------------------------------------------------------------- */ - -static inline int b1dma_tx_empty(unsigned int port) -{ - return inb(port + 0x03) & 0x1; -} - -static inline int b1dma_rx_full(unsigned int port) -{ - return inb(port + 0x02) & 0x1; -} - -static int b1dma_tolink(avmcard *card, void *buf, unsigned int len) -{ - unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ - unsigned char *s = (unsigned char *)buf; - while (len--) { - while (!b1dma_tx_empty(card->port) - && time_before(jiffies, stop)); - if (!b1dma_tx_empty(card->port)) - return -1; - t1outp(card->port, 0x01, *s++); - } - return 0; -} - -static int b1dma_fromlink(avmcard *card, void *buf, unsigned int len) -{ - unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ - unsigned char *s = (unsigned char *)buf; - while (len--) { - while (!b1dma_rx_full(card->port) - && time_before(jiffies, stop)); - if (!b1dma_rx_full(card->port)) - return -1; - *s++ = t1inp(card->port, 0x00); - } - return 0; -} - -static int WriteReg(avmcard *card, u32 reg, u8 val) -{ - u8 cmd = 0x00; - if (b1dma_tolink(card, &cmd, 1) == 0 - && b1dma_tolink(card, ®, 4) == 0) { - u32 tmp = val; - return b1dma_tolink(card, &tmp, 4); - } - return -1; -} - -static u8 ReadReg(avmcard *card, u32 reg) -{ - u8 cmd = 0x01; - if (b1dma_tolink(card, &cmd, 1) == 0 - && b1dma_tolink(card, ®, 4) == 0) { - u32 tmp; - if (b1dma_fromlink(card, &tmp, 4) == 0) - return (u8)tmp; - } - return 0xff; -} - -/* ------------------------------------------------------------- */ - -static inline void _put_byte(void **pp, u8 val) -{ - u8 *s = *pp; - *s++ = val; - *pp = s; -} - -static inline void _put_word(void **pp, u32 val) -{ - u8 *s = *pp; - *s++ = val & 0xff; - *s++ = (val >> 8) & 0xff; - *s++ = (val >> 16) & 0xff; - *s++ = (val >> 24) & 0xff; - *pp = s; -} - -static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len) -{ - unsigned i = len; - _put_word(pp, i); - while (i-- > 0) - _put_byte(pp, *dp++); -} - -static inline u8 _get_byte(void **pp) -{ - u8 *s = *pp; - u8 val; - val = *s++; - *pp = s; - return val; -} - -static inline u32 _get_word(void **pp) -{ - u8 *s = *pp; - u32 val; - val = *s++; - val |= (*s++ << 8); - val |= (*s++ << 16); - val |= (*s++ << 24); - *pp = s; - return val; -} - -static inline u32 _get_slice(void **pp, unsigned char *dp) -{ - unsigned int len, i; - - len = i = _get_word(pp); - while (i-- > 0) *dp++ = _get_byte(pp); - return len; -} - -/* ------------------------------------------------------------- */ - -void b1dma_reset(avmcard *card) -{ - card->csr = 0x0; - b1dma_writel(card, card->csr, AMCC_INTCSR); - b1dma_writel(card, 0, AMCC_MCSR); - b1dma_writel(card, 0, AMCC_RXLEN); - b1dma_writel(card, 0, AMCC_TXLEN); - - t1outp(card->port, 0x10, 0x00); - t1outp(card->port, 0x07, 0x00); - - b1dma_writel(card, 0, AMCC_MCSR); - mdelay(10); - b1dma_writel(card, 0x0f000000, AMCC_MCSR); /* reset all */ - mdelay(10); - b1dma_writel(card, 0, AMCC_MCSR); - if (card->cardtype == avm_t1pci) - mdelay(42); - else - mdelay(10); -} - -/* ------------------------------------------------------------- */ - -static int b1dma_detect(avmcard *card) -{ - b1dma_writel(card, 0, AMCC_MCSR); - mdelay(10); - b1dma_writel(card, 0x0f000000, AMCC_MCSR); /* reset all */ - mdelay(10); - b1dma_writel(card, 0, AMCC_MCSR); - mdelay(42); - - b1dma_writel(card, 0, AMCC_RXLEN); - b1dma_writel(card, 0, AMCC_TXLEN); - card->csr = 0x0; - b1dma_writel(card, card->csr, AMCC_INTCSR); - - if (b1dma_readl(card, AMCC_MCSR) != 0x000000E6) - return 1; - - b1dma_writel(card, 0xffffffff, AMCC_RXPTR); - b1dma_writel(card, 0xffffffff, AMCC_TXPTR); - if (b1dma_readl(card, AMCC_RXPTR) != 0xfffffffc - || b1dma_readl(card, AMCC_TXPTR) != 0xfffffffc) - return 2; - - b1dma_writel(card, 0x0, AMCC_RXPTR); - b1dma_writel(card, 0x0, AMCC_TXPTR); - if (b1dma_readl(card, AMCC_RXPTR) != 0x0 - || b1dma_readl(card, AMCC_TXPTR) != 0x0) - return 3; - - t1outp(card->port, 0x10, 0x00); - t1outp(card->port, 0x07, 0x00); - - t1outp(card->port, 0x02, 0x02); - t1outp(card->port, 0x03, 0x02); - - if ((t1inp(card->port, 0x02) & 0xFE) != 0x02 - || t1inp(card->port, 0x3) != 0x03) - return 4; - - t1outp(card->port, 0x02, 0x00); - t1outp(card->port, 0x03, 0x00); - - if ((t1inp(card->port, 0x02) & 0xFE) != 0x00 - || t1inp(card->port, 0x3) != 0x01) - return 5; - - return 0; -} - -int t1pci_detect(avmcard *card) -{ - int ret; - - if ((ret = b1dma_detect(card)) != 0) - return ret; - - /* Transputer test */ - - if (WriteReg(card, 0x80001000, 0x11) != 0 - || WriteReg(card, 0x80101000, 0x22) != 0 - || WriteReg(card, 0x80201000, 0x33) != 0 - || WriteReg(card, 0x80301000, 0x44) != 0) - return 6; - - if (ReadReg(card, 0x80001000) != 0x11 - || ReadReg(card, 0x80101000) != 0x22 - || ReadReg(card, 0x80201000) != 0x33 - || ReadReg(card, 0x80301000) != 0x44) - return 7; - - if (WriteReg(card, 0x80001000, 0x55) != 0 - || WriteReg(card, 0x80101000, 0x66) != 0 - || WriteReg(card, 0x80201000, 0x77) != 0 - || WriteReg(card, 0x80301000, 0x88) != 0) - return 8; - - if (ReadReg(card, 0x80001000) != 0x55 - || ReadReg(card, 0x80101000) != 0x66 - || ReadReg(card, 0x80201000) != 0x77 - || ReadReg(card, 0x80301000) != 0x88) - return 9; - - return 0; -} - -int b1pciv4_detect(avmcard *card) -{ - int ret, i; - - if ((ret = b1dma_detect(card)) != 0) - return ret; - - for (i = 0; i < 5; i++) { - if (WriteReg(card, 0x80A00000, 0x21) != 0) - return 6; - if ((ReadReg(card, 0x80A00000) & 0x01) != 0x01) - return 7; - } - for (i = 0; i < 5; i++) { - if (WriteReg(card, 0x80A00000, 0x20) != 0) - return 8; - if ((ReadReg(card, 0x80A00000) & 0x01) != 0x00) - return 9; - } - - return 0; -} - -static void b1dma_queue_tx(avmcard *card, struct sk_buff *skb) -{ - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - - skb_queue_tail(&card->dma->send_queue, skb); - - if (!(card->csr & EN_TX_TC_INT)) { - b1dma_dispatch_tx(card); - b1dma_writel(card, card->csr, AMCC_INTCSR); - } - - spin_unlock_irqrestore(&card->lock, flags); -} - -/* ------------------------------------------------------------- */ - -static void b1dma_dispatch_tx(avmcard *card) -{ - avmcard_dmainfo *dma = card->dma; - struct sk_buff *skb; - u8 cmd, subcmd; - u16 len; - u32 txlen; - void *p; - - skb = skb_dequeue(&dma->send_queue); - - len = CAPIMSG_LEN(skb->data); - - if (len) { - cmd = CAPIMSG_COMMAND(skb->data); - subcmd = CAPIMSG_SUBCOMMAND(skb->data); - - p = dma->sendbuf.dmabuf; - - if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { - u16 dlen = CAPIMSG_DATALEN(skb->data); - _put_byte(&p, SEND_DATA_B3_REQ); - _put_slice(&p, skb->data, len); - _put_slice(&p, skb->data + len, dlen); - } else { - _put_byte(&p, SEND_MESSAGE); - _put_slice(&p, skb->data, len); - } - txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf; -#ifdef AVM_B1DMA_DEBUG - printk(KERN_DEBUG "tx: put msg len=%d\n", txlen); -#endif - } else { - txlen = skb->len - 2; -#ifdef AVM_B1DMA_POLLDEBUG - if (skb->data[2] == SEND_POLLACK) - printk(KERN_INFO "%s: send ack\n", card->name); -#endif -#ifdef AVM_B1DMA_DEBUG - printk(KERN_DEBUG "tx: put 0x%x len=%d\n", - skb->data[2], txlen); -#endif - skb_copy_from_linear_data_offset(skb, 2, dma->sendbuf.dmabuf, - skb->len - 2); - } - txlen = (txlen + 3) & ~3; - - b1dma_writel(card, dma->sendbuf.dmaaddr, AMCC_TXPTR); - b1dma_writel(card, txlen, AMCC_TXLEN); - - card->csr |= EN_TX_TC_INT; - - dev_kfree_skb_any(skb); -} - -/* ------------------------------------------------------------- */ - -static void queue_pollack(avmcard *card) -{ - struct sk_buff *skb; - void *p; - - skb = alloc_skb(3, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost poll ack\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_POLLACK); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - b1dma_queue_tx(card, skb); -} - -/* ------------------------------------------------------------- */ - -static void b1dma_handle_rx(avmcard *card) -{ - avmctrl_info *cinfo = &card->ctrlinfo[0]; - avmcard_dmainfo *dma = card->dma; - struct capi_ctr *ctrl = &cinfo->capi_ctrl; - struct sk_buff *skb; - void *p = dma->recvbuf.dmabuf + 4; - u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize; - u8 b1cmd = _get_byte(&p); - -#ifdef AVM_B1DMA_DEBUG - printk(KERN_DEBUG "rx: 0x%x %lu\n", b1cmd, (unsigned long)dma->recvlen); -#endif - - switch (b1cmd) { - case RECEIVE_DATA_B3_IND: - - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - DataB3Len = _get_slice(&p, card->databuf); - - if (MsgLen < 30) { /* not CAPI 64Bit */ - memset(card->msgbuf + MsgLen, 0, 30 - MsgLen); - MsgLen = 30; - CAPIMSG_SETLEN(card->msgbuf, 30); - } - if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - skb_put_data(skb, card->databuf, DataB3Len); - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_MESSAGE: - - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF) { - spin_lock(&card->lock); - capilib_data_b3_conf(&cinfo->ncci_head, ApplId, - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - spin_unlock(&card->lock); - } - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_NEW_NCCI: - - ApplId = _get_word(&p); - NCCI = _get_word(&p); - WindowSize = _get_word(&p); - spin_lock(&card->lock); - capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize); - spin_unlock(&card->lock); - break; - - case RECEIVE_FREE_NCCI: - - ApplId = _get_word(&p); - NCCI = _get_word(&p); - - if (NCCI != 0xffffffff) { - spin_lock(&card->lock); - capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI); - spin_unlock(&card->lock); - } - break; - - case RECEIVE_START: -#ifdef AVM_B1DMA_POLLDEBUG - printk(KERN_INFO "%s: receive poll\n", card->name); -#endif - if (!suppress_pollack) - queue_pollack(card); - capi_ctr_resume_output(ctrl); - break; - - case RECEIVE_STOP: - capi_ctr_suspend_output(ctrl); - break; - - case RECEIVE_INIT: - - cinfo->versionlen = _get_slice(&p, cinfo->versionbuf); - b1_parse_version(cinfo); - printk(KERN_INFO "%s: %s-card (%s) now active\n", - card->name, - cinfo->version[VER_CARDTYPE], - cinfo->version[VER_DRIVER]); - capi_ctr_ready(ctrl); - break; - - case RECEIVE_TASK_READY: - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: task %d \"%s\" ready.\n", - card->name, ApplId, card->msgbuf); - break; - - case RECEIVE_DEBUGMSG: - MsgLen = _get_slice(&p, card->msgbuf); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); - break; - - default: - printk(KERN_ERR "%s: b1dma_interrupt: 0x%x ???\n", - card->name, b1cmd); - return; - } -} - -/* ------------------------------------------------------------- */ - -static void b1dma_handle_interrupt(avmcard *card) -{ - u32 status; - u32 newcsr; - - spin_lock(&card->lock); - - status = b1dma_readl(card, AMCC_INTCSR); - if ((status & ANY_S5933_INT) == 0) { - spin_unlock(&card->lock); - return; - } - - newcsr = card->csr | (status & ALL_INT); - if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT; - if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT; - b1dma_writel(card, newcsr, AMCC_INTCSR); - - if ((status & RX_TC_INT) != 0) { - struct avmcard_dmainfo *dma = card->dma; - u32 rxlen; - if (card->dma->recvlen == 0) { - rxlen = b1dma_readl(card, AMCC_RXLEN); - if (rxlen == 0) { - dma->recvlen = *((u32 *)dma->recvbuf.dmabuf); - rxlen = (dma->recvlen + 3) & ~3; - b1dma_writel(card, dma->recvbuf.dmaaddr + 4, AMCC_RXPTR); - b1dma_writel(card, rxlen, AMCC_RXLEN); -#ifdef AVM_B1DMA_DEBUG - } else { - printk(KERN_ERR "%s: rx not complete (%d).\n", - card->name, rxlen); -#endif - } - } else { - spin_unlock(&card->lock); - b1dma_handle_rx(card); - dma->recvlen = 0; - spin_lock(&card->lock); - b1dma_writel(card, dma->recvbuf.dmaaddr, AMCC_RXPTR); - b1dma_writel(card, 4, AMCC_RXLEN); - } - } - - if ((status & TX_TC_INT) != 0) { - if (skb_queue_empty(&card->dma->send_queue)) - card->csr &= ~EN_TX_TC_INT; - else - b1dma_dispatch_tx(card); - } - b1dma_writel(card, card->csr, AMCC_INTCSR); - - spin_unlock(&card->lock); -} - -irqreturn_t b1dma_interrupt(int interrupt, void *devptr) -{ - avmcard *card = devptr; - - b1dma_handle_interrupt(card); - return IRQ_HANDLED; -} - -/* ------------------------------------------------------------- */ - -static int b1dma_loaded(avmcard *card) -{ - unsigned long stop; - unsigned char ans; - unsigned long tout = 2; - unsigned int base = card->port; - - for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { - if (b1_tx_empty(base)) - break; - } - if (!b1_tx_empty(base)) { - printk(KERN_ERR "%s: b1dma_loaded: tx err, corrupted t4 file ?\n", - card->name); - return 0; - } - b1_put_byte(base, SEND_POLLACK); - for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { - if (b1_rx_full(base)) { - if ((ans = b1_get_byte(base)) == RECEIVE_POLLDWORD) { - return 1; - } - printk(KERN_ERR "%s: b1dma_loaded: got 0x%x, firmware not running in dword mode\n", card->name, ans); - return 0; - } - } - printk(KERN_ERR "%s: b1dma_loaded: firmware not running\n", card->name); - return 0; -} - -/* ------------------------------------------------------------- */ - -static void b1dma_send_init(avmcard *card) -{ - struct sk_buff *skb; - void *p; - - skb = alloc_skb(15, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost register appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_INIT); - _put_word(&p, CAPI_MAXAPPL); - _put_word(&p, AVM_NCCI_PER_CHANNEL * 30); - _put_word(&p, card->cardnr - 1); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - b1dma_queue_tx(card, skb); -} - -int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - int retval; - - b1dma_reset(card); - - if ((retval = b1_load_t4file(card, &data->firmware))) { - b1dma_reset(card); - printk(KERN_ERR "%s: failed to load t4file!!\n", - card->name); - return retval; - } - - if (data->configuration.len > 0 && data->configuration.data) { - if ((retval = b1_load_config(card, &data->configuration))) { - b1dma_reset(card); - printk(KERN_ERR "%s: failed to load config!!\n", - card->name); - return retval; - } - } - - if (!b1dma_loaded(card)) { - b1dma_reset(card); - printk(KERN_ERR "%s: failed to load t4file.\n", card->name); - return -EIO; - } - - card->csr = AVM_FLAG; - b1dma_writel(card, card->csr, AMCC_INTCSR); - b1dma_writel(card, EN_A2P_TRANSFERS | EN_P2A_TRANSFERS | A2P_HI_PRIORITY | - P2A_HI_PRIORITY | RESET_A2P_FLAGS | RESET_P2A_FLAGS, - AMCC_MCSR); - t1outp(card->port, 0x07, 0x30); - t1outp(card->port, 0x10, 0xF0); - - card->dma->recvlen = 0; - b1dma_writel(card, card->dma->recvbuf.dmaaddr, AMCC_RXPTR); - b1dma_writel(card, 4, AMCC_RXLEN); - card->csr |= EN_RX_TC_INT; - b1dma_writel(card, card->csr, AMCC_INTCSR); - - b1dma_send_init(card); - - return 0; -} - -void b1dma_reset_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - b1dma_reset(card); - - memset(cinfo->version, 0, sizeof(cinfo->version)); - capilib_release(&cinfo->ncci_head); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_down(ctrl); -} - -/* ------------------------------------------------------------- */ - -void b1dma_register_appl(struct capi_ctr *ctrl, - u16 appl, - capi_register_params *rp) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - struct sk_buff *skb; - int want = rp->level3cnt; - int nconn; - void *p; - - if (want > 0) nconn = want; - else nconn = ctrl->profile.nbchannel * -want; - if (nconn == 0) nconn = ctrl->profile.nbchannel; - - skb = alloc_skb(23, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost register appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_REGISTER); - _put_word(&p, appl); - _put_word(&p, 1024 * (nconn + 1)); - _put_word(&p, nconn); - _put_word(&p, rp->datablkcnt); - _put_word(&p, rp->datablklen); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - b1dma_queue_tx(card, skb); -} - -/* ------------------------------------------------------------- */ - -void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - struct sk_buff *skb; - void *p; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - capilib_release_appl(&cinfo->ncci_head, appl); - spin_unlock_irqrestore(&card->lock, flags); - - skb = alloc_skb(7, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost release appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_RELEASE); - _put_word(&p, appl); - - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - b1dma_queue_tx(card, skb); -} - -/* ------------------------------------------------------------- */ - -u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - u16 retval = CAPI_NOERROR; - - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) { - unsigned long flags; - spin_lock_irqsave(&card->lock, flags); - retval = capilib_data_b3_req(&cinfo->ncci_head, - CAPIMSG_APPID(skb->data), - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - spin_unlock_irqrestore(&card->lock, flags); - } - if (retval == CAPI_NOERROR) - b1dma_queue_tx(card, skb); - - return retval; -} - -/* ------------------------------------------------------------- */ - -int b1dma_proc_show(struct seq_file *m, void *v) -{ - struct capi_ctr *ctrl = m->private; - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - u8 flag; - char *s; - u32 txoff, txlen, rxoff, rxlen, csr; - unsigned long flags; - - seq_printf(m, "%-16s %s\n", "name", card->name); - seq_printf(m, "%-16s 0x%x\n", "io", card->port); - seq_printf(m, "%-16s %d\n", "irq", card->irq); - seq_printf(m, "%-16s 0x%lx\n", "membase", card->membase); - switch (card->cardtype) { - case avm_b1isa: s = "B1 ISA"; break; - case avm_b1pci: s = "B1 PCI"; break; - case avm_b1pcmcia: s = "B1 PCMCIA"; break; - case avm_m1: s = "M1"; break; - case avm_m2: s = "M2"; break; - case avm_t1isa: s = "T1 ISA (HEMA)"; break; - case avm_t1pci: s = "T1 PCI"; break; - case avm_c4: s = "C4"; break; - case avm_c2: s = "C2"; break; - default: s = "???"; break; - } - seq_printf(m, "%-16s %s\n", "type", s); - if ((s = cinfo->version[VER_DRIVER]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_driver", s); - if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_cardtype", s); - if ((s = cinfo->version[VER_SERIAL]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_serial", s); - - if (card->cardtype != avm_m1) { - flag = ((u8 *)(ctrl->profile.manu))[3]; - if (flag) - seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", - "protocol", - (flag & 0x01) ? " DSS1" : "", - (flag & 0x02) ? " CT1" : "", - (flag & 0x04) ? " VN3" : "", - (flag & 0x08) ? " NI1" : "", - (flag & 0x10) ? " AUSTEL" : "", - (flag & 0x20) ? " ESS" : "", - (flag & 0x40) ? " 1TR6" : "" - ); - } - if (card->cardtype != avm_m1) { - flag = ((u8 *)(ctrl->profile.manu))[5]; - if (flag) - seq_printf(m, "%-16s%s%s%s%s\n", - "linetype", - (flag & 0x01) ? " point to point" : "", - (flag & 0x02) ? " point to multipoint" : "", - (flag & 0x08) ? " leased line without D-channel" : "", - (flag & 0x04) ? " leased line with D-channel" : "" - ); - } - seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); - - - spin_lock_irqsave(&card->lock, flags); - - txoff = (dma_addr_t)b1dma_readl(card, AMCC_TXPTR)-card->dma->sendbuf.dmaaddr; - txlen = b1dma_readl(card, AMCC_TXLEN); - - rxoff = (dma_addr_t)b1dma_readl(card, AMCC_RXPTR)-card->dma->recvbuf.dmaaddr; - rxlen = b1dma_readl(card, AMCC_RXLEN); - - csr = b1dma_readl(card, AMCC_INTCSR); - - spin_unlock_irqrestore(&card->lock, flags); - - seq_printf(m, "%-16s 0x%lx\n", "csr (cached)", (unsigned long)card->csr); - seq_printf(m, "%-16s 0x%lx\n", "csr", (unsigned long)csr); - seq_printf(m, "%-16s %lu\n", "txoff", (unsigned long)txoff); - seq_printf(m, "%-16s %lu\n", "txlen", (unsigned long)txlen); - seq_printf(m, "%-16s %lu\n", "rxoff", (unsigned long)rxoff); - seq_printf(m, "%-16s %lu\n", "rxlen", (unsigned long)rxlen); - - return 0; -} -EXPORT_SYMBOL(b1dma_proc_show); - -/* ------------------------------------------------------------- */ - -EXPORT_SYMBOL(b1dma_reset); -EXPORT_SYMBOL(t1pci_detect); -EXPORT_SYMBOL(b1pciv4_detect); -EXPORT_SYMBOL(b1dma_interrupt); - -EXPORT_SYMBOL(b1dma_load_firmware); -EXPORT_SYMBOL(b1dma_reset_ctr); -EXPORT_SYMBOL(b1dma_register_appl); -EXPORT_SYMBOL(b1dma_release_appl); -EXPORT_SYMBOL(b1dma_send_message); - -static int __init b1dma_init(void) -{ - char *p; - char rev[32]; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, sizeof(rev)); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - printk(KERN_INFO "b1dma: revision %s\n", rev); - - return 0; -} - -static void __exit b1dma_exit(void) -{ -} - -module_init(b1dma_init); -module_exit(b1dma_exit); diff --git a/drivers/staging/isdn/avm/b1isa.c b/drivers/staging/isdn/avm/b1isa.c deleted file mode 100644 index cdfea72e0ef6..000000000000 --- a/drivers/staging/isdn/avm/b1isa.c +++ /dev/null @@ -1,243 +0,0 @@ -/* $Id: b1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $ - * - * Module for AVM B1 ISA-card. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" - -/* ------------------------------------------------------------- */ - -static char *revision = "$Revision: 1.1.2.3 $"; - -/* ------------------------------------------------------------- */ - -MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 ISA card"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------- */ - -static void b1isa_remove(struct pci_dev *pdev) -{ - avmctrl_info *cinfo = pci_get_drvdata(pdev); - avmcard *card; - - if (!cinfo) - return; - - card = cinfo->card; - - b1_reset(card->port); - b1_reset(card->port); - - detach_capi_ctr(&cinfo->capi_ctrl); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - b1_free_card(card); -} - -/* ------------------------------------------------------------- */ - -static char *b1isa_procinfo(struct capi_ctr *ctrl); - -static int b1isa_probe(struct pci_dev *pdev) -{ - avmctrl_info *cinfo; - avmcard *card; - int retval; - - card = b1_alloc_card(1); - if (!card) { - printk(KERN_WARNING "b1isa: no memory.\n"); - retval = -ENOMEM; - goto err; - } - - cinfo = card->ctrlinfo; - - card->port = pci_resource_start(pdev, 0); - card->irq = pdev->irq; - card->cardtype = avm_b1isa; - sprintf(card->name, "b1isa-%x", card->port); - - if (card->port != 0x150 && card->port != 0x250 - && card->port != 0x300 && card->port != 0x340) { - printk(KERN_WARNING "b1isa: invalid port 0x%x.\n", card->port); - retval = -EINVAL; - goto err_free; - } - if (b1_irq_table[card->irq & 0xf] == 0) { - printk(KERN_WARNING "b1isa: irq %d not valid.\n", card->irq); - retval = -EINVAL; - goto err_free; - } - if (!request_region(card->port, AVMB1_PORTLEN, card->name)) { - printk(KERN_WARNING "b1isa: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); - retval = -EBUSY; - goto err_free; - } - retval = request_irq(card->irq, b1_interrupt, 0, card->name, card); - if (retval) { - printk(KERN_ERR "b1isa: unable to get IRQ %d.\n", card->irq); - goto err_release_region; - } - b1_reset(card->port); - if ((retval = b1_detect(card->port, card->cardtype)) != 0) { - printk(KERN_NOTICE "b1isa: NO card at 0x%x (%d)\n", - card->port, retval); - retval = -ENODEV; - goto err_free_irq; - } - b1_reset(card->port); - b1_getrevision(card); - - cinfo->capi_ctrl.owner = THIS_MODULE; - cinfo->capi_ctrl.driver_name = "b1isa"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = b1_register_appl; - cinfo->capi_ctrl.release_appl = b1_release_appl; - cinfo->capi_ctrl.send_message = b1_send_message; - cinfo->capi_ctrl.load_firmware = b1_load_firmware; - cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; - cinfo->capi_ctrl.procinfo = b1isa_procinfo; - cinfo->capi_ctrl.proc_show = b1_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_ERR "b1isa: attach controller failed.\n"); - goto err_free_irq; - } - - printk(KERN_INFO "b1isa: AVM B1 ISA at i/o %#x, irq %d, revision %d\n", - card->port, card->irq, card->revision); - - pci_set_drvdata(pdev, cinfo); - return 0; - -err_free_irq: - free_irq(card->irq, card); -err_release_region: - release_region(card->port, AVMB1_PORTLEN); -err_free: - b1_free_card(card); -err: - return retval; -} - -static char *b1isa_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->revision : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -#define MAX_CARDS 4 -static struct pci_dev isa_dev[MAX_CARDS]; -static int io[MAX_CARDS]; -static int irq[MAX_CARDS]; - -module_param_hw_array(io, int, ioport, NULL, 0); -module_param_hw_array(irq, int, irq, NULL, 0); -MODULE_PARM_DESC(io, "I/O base address(es)"); -MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); - -static int b1isa_add_card(struct capi_driver *driver, capicardparams *data) -{ - int i; - - for (i = 0; i < MAX_CARDS; i++) { - if (isa_dev[i].resource[0].start) - continue; - - isa_dev[i].resource[0].start = data->port; - isa_dev[i].irq = data->irq; - - if (b1isa_probe(&isa_dev[i]) == 0) - return 0; - } - return -ENODEV; -} - -static struct capi_driver capi_driver_b1isa = { - .name = "b1isa", - .revision = "1.0", - .add_card = b1isa_add_card, -}; - -static int __init b1isa_init(void) -{ - char *p; - char rev[32]; - int i; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, 32); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - for (i = 0; i < MAX_CARDS; i++) { - if (!io[i]) - break; - - isa_dev[i].resource[0].start = io[i]; - isa_dev[i].irq = irq[i]; - - if (b1isa_probe(&isa_dev[i]) != 0) - return -ENODEV; - } - - strlcpy(capi_driver_b1isa.revision, rev, 32); - register_capi_driver(&capi_driver_b1isa); - printk(KERN_INFO "b1isa: revision %s\n", rev); - - return 0; -} - -static void __exit b1isa_exit(void) -{ - int i; - - for (i = 0; i < MAX_CARDS; i++) { - if (isa_dev[i].resource[0].start) - b1isa_remove(&isa_dev[i]); - } - unregister_capi_driver(&capi_driver_b1isa); -} - -module_init(b1isa_init); -module_exit(b1isa_exit); diff --git a/drivers/staging/isdn/avm/b1pci.c b/drivers/staging/isdn/avm/b1pci.c deleted file mode 100644 index b76b57a82c02..000000000000 --- a/drivers/staging/isdn/avm/b1pci.c +++ /dev/null @@ -1,416 +0,0 @@ -/* $Id: b1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ - * - * Module for AVM B1 PCI-card. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" - -/* ------------------------------------------------------------- */ - -static char *revision = "$Revision: 1.1.2.2 $"; - -/* ------------------------------------------------------------- */ - -static struct pci_device_id b1pci_pci_tbl[] = { - { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(pci, b1pci_pci_tbl); -MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 PCI card"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------- */ - -static char *b1pci_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->revision : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -static int b1pci_probe(struct capicardparams *p, struct pci_dev *pdev) -{ - avmcard *card; - avmctrl_info *cinfo; - int retval; - - card = b1_alloc_card(1); - if (!card) { - printk(KERN_WARNING "b1pci: no memory.\n"); - retval = -ENOMEM; - goto err; - } - - cinfo = card->ctrlinfo; - sprintf(card->name, "b1pci-%x", p->port); - card->port = p->port; - card->irq = p->irq; - card->cardtype = avm_b1pci; - - if (!request_region(card->port, AVMB1_PORTLEN, card->name)) { - printk(KERN_WARNING "b1pci: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); - retval = -EBUSY; - goto err_free; - } - b1_reset(card->port); - retval = b1_detect(card->port, card->cardtype); - if (retval) { - printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n", - card->port, retval); - retval = -ENODEV; - goto err_release_region; - } - b1_reset(card->port); - b1_getrevision(card); - - retval = request_irq(card->irq, b1_interrupt, IRQF_SHARED, card->name, card); - if (retval) { - printk(KERN_ERR "b1pci: unable to get IRQ %d.\n", card->irq); - retval = -EBUSY; - goto err_release_region; - } - - cinfo->capi_ctrl.driver_name = "b1pci"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = b1_register_appl; - cinfo->capi_ctrl.release_appl = b1_release_appl; - cinfo->capi_ctrl.send_message = b1_send_message; - cinfo->capi_ctrl.load_firmware = b1_load_firmware; - cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; - cinfo->capi_ctrl.procinfo = b1pci_procinfo; - cinfo->capi_ctrl.proc_show = b1_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - cinfo->capi_ctrl.owner = THIS_MODULE; - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_ERR "b1pci: attach controller failed.\n"); - goto err_free_irq; - } - - if (card->revision >= 4) { - printk(KERN_INFO "b1pci: AVM B1 PCI V4 at i/o %#x, irq %d, revision %d (no dma)\n", - card->port, card->irq, card->revision); - } else { - printk(KERN_INFO "b1pci: AVM B1 PCI at i/o %#x, irq %d, revision %d\n", - card->port, card->irq, card->revision); - } - - pci_set_drvdata(pdev, card); - return 0; - -err_free_irq: - free_irq(card->irq, card); -err_release_region: - release_region(card->port, AVMB1_PORTLEN); -err_free: - b1_free_card(card); -err: - return retval; -} - -static void b1pci_remove(struct pci_dev *pdev) -{ - avmcard *card = pci_get_drvdata(pdev); - avmctrl_info *cinfo = card->ctrlinfo; - unsigned int port = card->port; - - b1_reset(port); - b1_reset(port); - - detach_capi_ctr(&cinfo->capi_ctrl); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - b1_free_card(card); -} - -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 -/* ------------------------------------------------------------- */ - -static char *b1pciv4_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx r%d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->membase : 0, - cinfo->card ? cinfo->card->revision : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -static int b1pciv4_probe(struct capicardparams *p, struct pci_dev *pdev) -{ - avmcard *card; - avmctrl_info *cinfo; - int retval; - - card = b1_alloc_card(1); - if (!card) { - printk(KERN_WARNING "b1pci: no memory.\n"); - retval = -ENOMEM; - goto err; - } - - card->dma = avmcard_dma_alloc("b1pci", pdev, 2048 + 128, 2048 + 128); - if (!card->dma) { - printk(KERN_WARNING "b1pci: dma alloc.\n"); - retval = -ENOMEM; - goto err_free; - } - - cinfo = card->ctrlinfo; - sprintf(card->name, "b1pciv4-%x", p->port); - card->port = p->port; - card->irq = p->irq; - card->membase = p->membase; - card->cardtype = avm_b1pci; - - if (!request_region(card->port, AVMB1_PORTLEN, card->name)) { - printk(KERN_WARNING "b1pci: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); - retval = -EBUSY; - goto err_free_dma; - } - - card->mbase = ioremap(card->membase, 64); - if (!card->mbase) { - printk(KERN_NOTICE "b1pci: can't remap memory at 0x%lx\n", - card->membase); - retval = -ENOMEM; - goto err_release_region; - } - - b1dma_reset(card); - - retval = b1pciv4_detect(card); - if (retval) { - printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n", - card->port, retval); - retval = -ENODEV; - goto err_unmap; - } - b1dma_reset(card); - b1_getrevision(card); - - retval = request_irq(card->irq, b1dma_interrupt, IRQF_SHARED, card->name, card); - if (retval) { - printk(KERN_ERR "b1pci: unable to get IRQ %d.\n", - card->irq); - retval = -EBUSY; - goto err_unmap; - } - - cinfo->capi_ctrl.owner = THIS_MODULE; - cinfo->capi_ctrl.driver_name = "b1pciv4"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = b1dma_register_appl; - cinfo->capi_ctrl.release_appl = b1dma_release_appl; - cinfo->capi_ctrl.send_message = b1dma_send_message; - cinfo->capi_ctrl.load_firmware = b1dma_load_firmware; - cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr; - cinfo->capi_ctrl.procinfo = b1pciv4_procinfo; - cinfo->capi_ctrl.proc_show = b1dma_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_ERR "b1pci: attach controller failed.\n"); - goto err_free_irq; - } - card->cardnr = cinfo->capi_ctrl.cnr; - - printk(KERN_INFO "b1pci: AVM B1 PCI V4 at i/o %#x, irq %d, mem %#lx, revision %d (dma)\n", - card->port, card->irq, card->membase, card->revision); - - pci_set_drvdata(pdev, card); - return 0; - -err_free_irq: - free_irq(card->irq, card); -err_unmap: - iounmap(card->mbase); -err_release_region: - release_region(card->port, AVMB1_PORTLEN); -err_free_dma: - avmcard_dma_free(card->dma); -err_free: - b1_free_card(card); -err: - return retval; - -} - -static void b1pciv4_remove(struct pci_dev *pdev) -{ - avmcard *card = pci_get_drvdata(pdev); - avmctrl_info *cinfo = card->ctrlinfo; - - b1dma_reset(card); - - detach_capi_ctr(&cinfo->capi_ctrl); - free_irq(card->irq, card); - iounmap(card->mbase); - release_region(card->port, AVMB1_PORTLEN); - avmcard_dma_free(card->dma); - b1_free_card(card); -} - -#endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */ - -static int b1pci_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct capicardparams param; - int retval; - - if (pci_enable_device(pdev) < 0) { - printk(KERN_ERR "b1pci: failed to enable AVM-B1\n"); - return -ENODEV; - } - param.irq = pdev->irq; - - if (pci_resource_start(pdev, 2)) { /* B1 PCI V4 */ -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - pci_set_master(pdev); -#endif - param.membase = pci_resource_start(pdev, 0); - param.port = pci_resource_start(pdev, 2); - - printk(KERN_INFO "b1pci: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n", - param.port, param.irq, param.membase); -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - retval = b1pciv4_probe(¶m, pdev); -#else - retval = b1pci_probe(¶m, pdev); -#endif - if (retval != 0) { - printk(KERN_ERR "b1pci: no AVM-B1 V4 at i/o %#x, irq %d, mem %#x detected\n", - param.port, param.irq, param.membase); - } - } else { - param.membase = 0; - param.port = pci_resource_start(pdev, 1); - - printk(KERN_INFO "b1pci: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n", - param.port, param.irq); - retval = b1pci_probe(¶m, pdev); - if (retval != 0) { - printk(KERN_ERR "b1pci: no AVM-B1 at i/o %#x, irq %d detected\n", - param.port, param.irq); - } - } - return retval; -} - -static void b1pci_pci_remove(struct pci_dev *pdev) -{ -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - avmcard *card = pci_get_drvdata(pdev); - - if (card->dma) - b1pciv4_remove(pdev); - else - b1pci_remove(pdev); -#else - b1pci_remove(pdev); -#endif -} - -static struct pci_driver b1pci_pci_driver = { - .name = "b1pci", - .id_table = b1pci_pci_tbl, - .probe = b1pci_pci_probe, - .remove = b1pci_pci_remove, -}; - -static struct capi_driver capi_driver_b1pci = { - .name = "b1pci", - .revision = "1.0", -}; -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 -static struct capi_driver capi_driver_b1pciv4 = { - .name = "b1pciv4", - .revision = "1.0", -}; -#endif - -static int __init b1pci_init(void) -{ - char *p; - char rev[32]; - int err; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, 32); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - - err = pci_register_driver(&b1pci_pci_driver); - if (!err) { - strlcpy(capi_driver_b1pci.revision, rev, 32); - register_capi_driver(&capi_driver_b1pci); -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - strlcpy(capi_driver_b1pciv4.revision, rev, 32); - register_capi_driver(&capi_driver_b1pciv4); -#endif - printk(KERN_INFO "b1pci: revision %s\n", rev); - } - return err; -} - -static void __exit b1pci_exit(void) -{ - unregister_capi_driver(&capi_driver_b1pci); -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - unregister_capi_driver(&capi_driver_b1pciv4); -#endif - pci_unregister_driver(&b1pci_pci_driver); -} - -module_init(b1pci_init); -module_exit(b1pci_exit); diff --git a/drivers/staging/isdn/avm/b1pcmcia.c b/drivers/staging/isdn/avm/b1pcmcia.c deleted file mode 100644 index 3aca16e62902..000000000000 --- a/drivers/staging/isdn/avm/b1pcmcia.c +++ /dev/null @@ -1,224 +0,0 @@ -/* $Id: b1pcmcia.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ - * - * Module for AVM B1/M1/M2 PCMCIA-card. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" - -/* ------------------------------------------------------------- */ - -static char *revision = "$Revision: 1.1.2.2 $"; - -/* ------------------------------------------------------------- */ - -MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM PCMCIA cards"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------- */ - -static void b1pcmcia_remove_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - - b1_reset(port); - b1_reset(port); - - detach_capi_ctr(ctrl); - free_irq(card->irq, card); - b1_free_card(card); -} - -/* ------------------------------------------------------------- */ - -static LIST_HEAD(cards); - -static char *b1pcmcia_procinfo(struct capi_ctr *ctrl); - -static int b1pcmcia_add_card(unsigned int port, unsigned irq, - enum avmcardtype cardtype) -{ - avmctrl_info *cinfo; - avmcard *card; - char *cardname; - int retval; - - card = b1_alloc_card(1); - if (!card) { - printk(KERN_WARNING "b1pcmcia: no memory.\n"); - retval = -ENOMEM; - goto err; - } - cinfo = card->ctrlinfo; - - switch (cardtype) { - case avm_m1: sprintf(card->name, "m1-%x", port); break; - case avm_m2: sprintf(card->name, "m2-%x", port); break; - default: sprintf(card->name, "b1pcmcia-%x", port); break; - } - card->port = port; - card->irq = irq; - card->cardtype = cardtype; - - retval = request_irq(card->irq, b1_interrupt, IRQF_SHARED, card->name, card); - if (retval) { - printk(KERN_ERR "b1pcmcia: unable to get IRQ %d.\n", - card->irq); - retval = -EBUSY; - goto err_free; - } - b1_reset(card->port); - if ((retval = b1_detect(card->port, card->cardtype)) != 0) { - printk(KERN_NOTICE "b1pcmcia: NO card at 0x%x (%d)\n", - card->port, retval); - retval = -ENODEV; - goto err_free_irq; - } - b1_reset(card->port); - b1_getrevision(card); - - cinfo->capi_ctrl.owner = THIS_MODULE; - cinfo->capi_ctrl.driver_name = "b1pcmcia"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = b1_register_appl; - cinfo->capi_ctrl.release_appl = b1_release_appl; - cinfo->capi_ctrl.send_message = b1_send_message; - cinfo->capi_ctrl.load_firmware = b1_load_firmware; - cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; - cinfo->capi_ctrl.procinfo = b1pcmcia_procinfo; - cinfo->capi_ctrl.proc_show = b1_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_ERR "b1pcmcia: attach controller failed.\n"); - goto err_free_irq; - } - switch (cardtype) { - case avm_m1: cardname = "M1"; break; - case avm_m2: cardname = "M2"; break; - default: cardname = "B1 PCMCIA"; break; - } - - printk(KERN_INFO "b1pcmcia: AVM %s at i/o %#x, irq %d, revision %d\n", - cardname, card->port, card->irq, card->revision); - - list_add(&card->list, &cards); - return cinfo->capi_ctrl.cnr; - -err_free_irq: - free_irq(card->irq, card); -err_free: - b1_free_card(card); -err: - return retval; -} - -/* ------------------------------------------------------------- */ - -static char *b1pcmcia_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->revision : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -int b1pcmcia_addcard_b1(unsigned int port, unsigned irq) -{ - return b1pcmcia_add_card(port, irq, avm_b1pcmcia); -} - -int b1pcmcia_addcard_m1(unsigned int port, unsigned irq) -{ - return b1pcmcia_add_card(port, irq, avm_m1); -} - -int b1pcmcia_addcard_m2(unsigned int port, unsigned irq) -{ - return b1pcmcia_add_card(port, irq, avm_m2); -} - -int b1pcmcia_delcard(unsigned int port, unsigned irq) -{ - struct list_head *l; - avmcard *card; - - list_for_each(l, &cards) { - card = list_entry(l, avmcard, list); - if (card->port == port && card->irq == irq) { - b1pcmcia_remove_ctr(&card->ctrlinfo[0].capi_ctrl); - return 0; - } - } - return -ESRCH; -} - -EXPORT_SYMBOL(b1pcmcia_addcard_b1); -EXPORT_SYMBOL(b1pcmcia_addcard_m1); -EXPORT_SYMBOL(b1pcmcia_addcard_m2); -EXPORT_SYMBOL(b1pcmcia_delcard); - -static struct capi_driver capi_driver_b1pcmcia = { - .name = "b1pcmcia", - .revision = "1.0", -}; - -static int __init b1pcmcia_init(void) -{ - char *p; - char rev[32]; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, 32); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - strlcpy(capi_driver_b1pcmcia.revision, rev, 32); - register_capi_driver(&capi_driver_b1pcmcia); - printk(KERN_INFO "b1pci: revision %s\n", rev); - - return 0; -} - -static void __exit b1pcmcia_exit(void) -{ - unregister_capi_driver(&capi_driver_b1pcmcia); -} - -module_init(b1pcmcia_init); -module_exit(b1pcmcia_exit); diff --git a/drivers/staging/isdn/avm/c4.c b/drivers/staging/isdn/avm/c4.c deleted file mode 100644 index ac72cd204c4d..000000000000 --- a/drivers/staging/isdn/avm/c4.c +++ /dev/null @@ -1,1317 +0,0 @@ -/* $Id: c4.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ - * - * Module for AVM C4 & C2 card. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" - -#undef AVM_C4_DEBUG -#undef AVM_C4_POLLDEBUG - -/* ------------------------------------------------------------- */ - -static char *revision = "$Revision: 1.1.2.2 $"; - -/* ------------------------------------------------------------- */ - -static bool suppress_pollack; - -static const struct pci_device_id c4_pci_tbl[] = { - { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, 0, 0, (unsigned long)4 }, - { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C2, 0, 0, (unsigned long)2 }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(pci, c4_pci_tbl); -MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM C2/C4 cards"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); -module_param(suppress_pollack, bool, 0); - -/* ------------------------------------------------------------- */ - -static void c4_dispatch_tx(avmcard *card); - -/* ------------------------------------------------------------- */ - -#define DC21285_DRAM_A0MR 0x40000000 -#define DC21285_DRAM_A1MR 0x40004000 -#define DC21285_DRAM_A2MR 0x40008000 -#define DC21285_DRAM_A3MR 0x4000C000 - -#define CAS_OFFSET 0x88 - -#define DC21285_ARMCSR_BASE 0x42000000 - -#define PCI_OUT_INT_STATUS 0x30 -#define PCI_OUT_INT_MASK 0x34 -#define MAILBOX_0 0x50 -#define MAILBOX_1 0x54 -#define MAILBOX_2 0x58 -#define MAILBOX_3 0x5C -#define DOORBELL 0x60 -#define DOORBELL_SETUP 0x64 - -#define CHAN_1_CONTROL 0x90 -#define CHAN_2_CONTROL 0xB0 -#define DRAM_TIMING 0x10C -#define DRAM_ADDR_SIZE_0 0x110 -#define DRAM_ADDR_SIZE_1 0x114 -#define DRAM_ADDR_SIZE_2 0x118 -#define DRAM_ADDR_SIZE_3 0x11C -#define SA_CONTROL 0x13C -#define XBUS_CYCLE 0x148 -#define XBUS_STROBE 0x14C -#define DBELL_PCI_MASK 0x150 -#define DBELL_SA_MASK 0x154 - -#define SDRAM_SIZE 0x1000000 - -/* ------------------------------------------------------------- */ - -#define MBOX_PEEK_POKE MAILBOX_0 - -#define DBELL_ADDR 0x01 -#define DBELL_DATA 0x02 -#define DBELL_RNWR 0x40 -#define DBELL_INIT 0x80 - -/* ------------------------------------------------------------- */ - -#define MBOX_UP_ADDR MAILBOX_0 -#define MBOX_UP_LEN MAILBOX_1 -#define MBOX_DOWN_ADDR MAILBOX_2 -#define MBOX_DOWN_LEN MAILBOX_3 - -#define DBELL_UP_HOST 0x00000100 -#define DBELL_UP_ARM 0x00000200 -#define DBELL_DOWN_HOST 0x00000400 -#define DBELL_DOWN_ARM 0x00000800 -#define DBELL_RESET_HOST 0x40000000 -#define DBELL_RESET_ARM 0x80000000 - -/* ------------------------------------------------------------- */ - -#define DRAM_TIMING_DEF 0x001A01A5 -#define DRAM_AD_SZ_DEF0 0x00000045 -#define DRAM_AD_SZ_NULL 0x00000000 - -#define SA_CTL_ALLRIGHT 0x64AA0271 - -#define INIT_XBUS_CYCLE 0x100016DB -#define INIT_XBUS_STROBE 0xF1F1F1F1 - -/* ------------------------------------------------------------- */ - -#define RESET_TIMEOUT (15 * HZ) /* 15 sec */ -#define PEEK_POKE_TIMEOUT (HZ / 10) /* 0.1 sec */ - -/* ------------------------------------------------------------- */ - -#define c4outmeml(addr, value) writel(value, addr) -#define c4inmeml(addr) readl(addr) -#define c4outmemw(addr, value) writew(value, addr) -#define c4inmemw(addr) readw(addr) -#define c4outmemb(addr, value) writeb(value, addr) -#define c4inmemb(addr) readb(addr) - -/* ------------------------------------------------------------- */ - -static inline int wait_for_doorbell(avmcard *card, unsigned long t) -{ - unsigned long stop; - - stop = jiffies + t; - while (c4inmeml(card->mbase + DOORBELL) != 0xffffffff) { - if (!time_before(jiffies, stop)) - return -1; - mb(); - } - return 0; -} - -static int c4_poke(avmcard *card, unsigned long off, unsigned long value) -{ - - if (wait_for_doorbell(card, HZ / 10) < 0) - return -1; - - c4outmeml(card->mbase + MBOX_PEEK_POKE, off); - c4outmeml(card->mbase + DOORBELL, DBELL_ADDR); - - if (wait_for_doorbell(card, HZ / 10) < 0) - return -1; - - c4outmeml(card->mbase + MBOX_PEEK_POKE, value); - c4outmeml(card->mbase + DOORBELL, DBELL_DATA | DBELL_ADDR); - - return 0; -} - -static int c4_peek(avmcard *card, unsigned long off, unsigned long *valuep) -{ - if (wait_for_doorbell(card, HZ / 10) < 0) - return -1; - - c4outmeml(card->mbase + MBOX_PEEK_POKE, off); - c4outmeml(card->mbase + DOORBELL, DBELL_RNWR | DBELL_ADDR); - - if (wait_for_doorbell(card, HZ / 10) < 0) - return -1; - - *valuep = c4inmeml(card->mbase + MBOX_PEEK_POKE); - - return 0; -} - -/* ------------------------------------------------------------- */ - -static int c4_load_t4file(avmcard *card, capiloaddatapart *t4file) -{ - u32 val; - unsigned char *dp; - u_int left; - u32 loadoff = 0; - - dp = t4file->data; - left = t4file->len; - while (left >= sizeof(u32)) { - if (t4file->user) { - if (copy_from_user(&val, dp, sizeof(val))) - return -EFAULT; - } else { - memcpy(&val, dp, sizeof(val)); - } - if (c4_poke(card, loadoff, val)) { - printk(KERN_ERR "%s: corrupted firmware file ?\n", - card->name); - return -EIO; - } - left -= sizeof(u32); - dp += sizeof(u32); - loadoff += sizeof(u32); - } - if (left) { - val = 0; - if (t4file->user) { - if (copy_from_user(&val, dp, left)) - return -EFAULT; - } else { - memcpy(&val, dp, left); - } - if (c4_poke(card, loadoff, val)) { - printk(KERN_ERR "%s: corrupted firmware file ?\n", - card->name); - return -EIO; - } - } - return 0; -} - -/* ------------------------------------------------------------- */ - -static inline void _put_byte(void **pp, u8 val) -{ - u8 *s = *pp; - *s++ = val; - *pp = s; -} - -static inline void _put_word(void **pp, u32 val) -{ - u8 *s = *pp; - *s++ = val & 0xff; - *s++ = (val >> 8) & 0xff; - *s++ = (val >> 16) & 0xff; - *s++ = (val >> 24) & 0xff; - *pp = s; -} - -static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len) -{ - unsigned i = len; - _put_word(pp, i); - while (i-- > 0) - _put_byte(pp, *dp++); -} - -static inline u8 _get_byte(void **pp) -{ - u8 *s = *pp; - u8 val; - val = *s++; - *pp = s; - return val; -} - -static inline u32 _get_word(void **pp) -{ - u8 *s = *pp; - u32 val; - val = *s++; - val |= (*s++ << 8); - val |= (*s++ << 16); - val |= (*s++ << 24); - *pp = s; - return val; -} - -static inline u32 _get_slice(void **pp, unsigned char *dp) -{ - unsigned int len, i; - - len = i = _get_word(pp); - while (i-- > 0) *dp++ = _get_byte(pp); - return len; -} - -/* ------------------------------------------------------------- */ - -static void c4_reset(avmcard *card) -{ - unsigned long stop; - - c4outmeml(card->mbase + DOORBELL, DBELL_RESET_ARM); - - stop = jiffies + HZ * 10; - while (c4inmeml(card->mbase + DOORBELL) != 0xffffffff) { - if (!time_before(jiffies, stop)) - return; - c4outmeml(card->mbase + DOORBELL, DBELL_ADDR); - mb(); - } - - c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0); - c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0); -} - -/* ------------------------------------------------------------- */ - -static int c4_detect(avmcard *card) -{ - unsigned long stop, dummy; - - c4outmeml(card->mbase + PCI_OUT_INT_MASK, 0x0c); - if (c4inmeml(card->mbase + PCI_OUT_INT_MASK) != 0x0c) - return 1; - - c4outmeml(card->mbase + DOORBELL, DBELL_RESET_ARM); - - stop = jiffies + HZ * 10; - while (c4inmeml(card->mbase + DOORBELL) != 0xffffffff) { - if (!time_before(jiffies, stop)) - return 2; - c4outmeml(card->mbase + DOORBELL, DBELL_ADDR); - mb(); - } - - c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0); - c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0); - - c4outmeml(card->mbase + MAILBOX_0, 0x55aa55aa); - if (c4inmeml(card->mbase + MAILBOX_0) != 0x55aa55aa) return 3; - - c4outmeml(card->mbase + MAILBOX_0, 0xaa55aa55); - if (c4inmeml(card->mbase + MAILBOX_0) != 0xaa55aa55) return 4; - - if (c4_poke(card, DC21285_ARMCSR_BASE + DBELL_SA_MASK, 0)) return 5; - if (c4_poke(card, DC21285_ARMCSR_BASE + DBELL_PCI_MASK, 0)) return 6; - if (c4_poke(card, DC21285_ARMCSR_BASE + SA_CONTROL, SA_CTL_ALLRIGHT)) - return 7; - if (c4_poke(card, DC21285_ARMCSR_BASE + XBUS_CYCLE, INIT_XBUS_CYCLE)) - return 8; - if (c4_poke(card, DC21285_ARMCSR_BASE + XBUS_STROBE, INIT_XBUS_STROBE)) - return 8; - if (c4_poke(card, DC21285_ARMCSR_BASE + DRAM_TIMING, 0)) return 9; - - mdelay(1); - - if (c4_peek(card, DC21285_DRAM_A0MR, &dummy)) return 10; - if (c4_peek(card, DC21285_DRAM_A1MR, &dummy)) return 11; - if (c4_peek(card, DC21285_DRAM_A2MR, &dummy)) return 12; - if (c4_peek(card, DC21285_DRAM_A3MR, &dummy)) return 13; - - if (c4_poke(card, DC21285_DRAM_A0MR + CAS_OFFSET, 0)) return 14; - if (c4_poke(card, DC21285_DRAM_A1MR + CAS_OFFSET, 0)) return 15; - if (c4_poke(card, DC21285_DRAM_A2MR + CAS_OFFSET, 0)) return 16; - if (c4_poke(card, DC21285_DRAM_A3MR + CAS_OFFSET, 0)) return 17; - - mdelay(1); - - if (c4_poke(card, DC21285_ARMCSR_BASE + DRAM_TIMING, DRAM_TIMING_DEF)) - return 18; - - if (c4_poke(card, DC21285_ARMCSR_BASE + DRAM_ADDR_SIZE_0, DRAM_AD_SZ_DEF0)) - return 19; - if (c4_poke(card, DC21285_ARMCSR_BASE + DRAM_ADDR_SIZE_1, DRAM_AD_SZ_NULL)) - return 20; - if (c4_poke(card, DC21285_ARMCSR_BASE + DRAM_ADDR_SIZE_2, DRAM_AD_SZ_NULL)) - return 21; - if (c4_poke(card, DC21285_ARMCSR_BASE + DRAM_ADDR_SIZE_3, DRAM_AD_SZ_NULL)) - return 22; - - /* Transputer test */ - - if (c4_poke(card, 0x000000, 0x11111111) - || c4_poke(card, 0x400000, 0x22222222) - || c4_poke(card, 0x800000, 0x33333333) - || c4_poke(card, 0xC00000, 0x44444444)) - return 23; - - if (c4_peek(card, 0x000000, &dummy) || dummy != 0x11111111 - || c4_peek(card, 0x400000, &dummy) || dummy != 0x22222222 - || c4_peek(card, 0x800000, &dummy) || dummy != 0x33333333 - || c4_peek(card, 0xC00000, &dummy) || dummy != 0x44444444) - return 24; - - if (c4_poke(card, 0x000000, 0x55555555) - || c4_poke(card, 0x400000, 0x66666666) - || c4_poke(card, 0x800000, 0x77777777) - || c4_poke(card, 0xC00000, 0x88888888)) - return 25; - - if (c4_peek(card, 0x000000, &dummy) || dummy != 0x55555555 - || c4_peek(card, 0x400000, &dummy) || dummy != 0x66666666 - || c4_peek(card, 0x800000, &dummy) || dummy != 0x77777777 - || c4_peek(card, 0xC00000, &dummy) || dummy != 0x88888888) - return 26; - - return 0; -} - -/* ------------------------------------------------------------- */ - -static void c4_dispatch_tx(avmcard *card) -{ - avmcard_dmainfo *dma = card->dma; - struct sk_buff *skb; - u8 cmd, subcmd; - u16 len; - u32 txlen; - void *p; - - - if (card->csr & DBELL_DOWN_ARM) { /* tx busy */ - return; - } - - skb = skb_dequeue(&dma->send_queue); - if (!skb) { -#ifdef AVM_C4_DEBUG - printk(KERN_DEBUG "%s: tx underrun\n", card->name); -#endif - return; - } - - len = CAPIMSG_LEN(skb->data); - - if (len) { - cmd = CAPIMSG_COMMAND(skb->data); - subcmd = CAPIMSG_SUBCOMMAND(skb->data); - - p = dma->sendbuf.dmabuf; - - if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { - u16 dlen = CAPIMSG_DATALEN(skb->data); - _put_byte(&p, SEND_DATA_B3_REQ); - _put_slice(&p, skb->data, len); - _put_slice(&p, skb->data + len, dlen); - } else { - _put_byte(&p, SEND_MESSAGE); - _put_slice(&p, skb->data, len); - } - txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf; -#ifdef AVM_C4_DEBUG - printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen); -#endif - } else { - txlen = skb->len - 2; -#ifdef AVM_C4_POLLDEBUG - if (skb->data[2] == SEND_POLLACK) - printk(KERN_INFO "%s: ack to c4\n", card->name); -#endif -#ifdef AVM_C4_DEBUG - printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n", - card->name, skb->data[2], txlen); -#endif - skb_copy_from_linear_data_offset(skb, 2, dma->sendbuf.dmabuf, - skb->len - 2); - } - txlen = (txlen + 3) & ~3; - - c4outmeml(card->mbase + MBOX_DOWN_ADDR, dma->sendbuf.dmaaddr); - c4outmeml(card->mbase + MBOX_DOWN_LEN, txlen); - - card->csr |= DBELL_DOWN_ARM; - - c4outmeml(card->mbase + DOORBELL, DBELL_DOWN_ARM); - - dev_kfree_skb_any(skb); -} - -/* ------------------------------------------------------------- */ - -static void queue_pollack(avmcard *card) -{ - struct sk_buff *skb; - void *p; - - skb = alloc_skb(3, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost poll ack\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_POLLACK); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - c4_dispatch_tx(card); -} - -/* ------------------------------------------------------------- */ - -static void c4_handle_rx(avmcard *card) -{ - avmcard_dmainfo *dma = card->dma; - struct capi_ctr *ctrl; - avmctrl_info *cinfo; - struct sk_buff *skb; - void *p = dma->recvbuf.dmabuf; - u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize; - u8 b1cmd = _get_byte(&p); - u32 cidx; - - -#ifdef AVM_C4_DEBUG - printk(KERN_DEBUG "%s: rx 0x%x len=%lu\n", card->name, - b1cmd, (unsigned long)dma->recvlen); -#endif - - switch (b1cmd) { - case RECEIVE_DATA_B3_IND: - - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - DataB3Len = _get_slice(&p, card->databuf); - cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr; - if (cidx >= card->nlogcontr) cidx = 0; - ctrl = &card->ctrlinfo[cidx].capi_ctrl; - - if (MsgLen < 30) { /* not CAPI 64Bit */ - memset(card->msgbuf + MsgLen, 0, 30 - MsgLen); - MsgLen = 30; - CAPIMSG_SETLEN(card->msgbuf, 30); - } - if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - skb_put_data(skb, card->databuf, DataB3Len); - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_MESSAGE: - - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr; - if (cidx >= card->nlogcontr) cidx = 0; - cinfo = &card->ctrlinfo[cidx]; - ctrl = &card->ctrlinfo[cidx].capi_ctrl; - - if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF) - capilib_data_b3_conf(&cinfo->ncci_head, ApplId, - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_NEW_NCCI: - - ApplId = _get_word(&p); - NCCI = _get_word(&p); - WindowSize = _get_word(&p); - cidx = (NCCI & 0x7f) - card->cardnr; - if (cidx >= card->nlogcontr) cidx = 0; - - capilib_new_ncci(&card->ctrlinfo[cidx].ncci_head, ApplId, NCCI, WindowSize); - - break; - - case RECEIVE_FREE_NCCI: - - ApplId = _get_word(&p); - NCCI = _get_word(&p); - - if (NCCI != 0xffffffff) { - cidx = (NCCI & 0x7f) - card->cardnr; - if (cidx >= card->nlogcontr) cidx = 0; - capilib_free_ncci(&card->ctrlinfo[cidx].ncci_head, ApplId, NCCI); - } - break; - - case RECEIVE_START: -#ifdef AVM_C4_POLLDEBUG - printk(KERN_INFO "%s: poll from c4\n", card->name); -#endif - if (!suppress_pollack) - queue_pollack(card); - for (cidx = 0; cidx < card->nr_controllers; cidx++) { - ctrl = &card->ctrlinfo[cidx].capi_ctrl; - capi_ctr_resume_output(ctrl); - } - break; - - case RECEIVE_STOP: - for (cidx = 0; cidx < card->nr_controllers; cidx++) { - ctrl = &card->ctrlinfo[cidx].capi_ctrl; - capi_ctr_suspend_output(ctrl); - } - break; - - case RECEIVE_INIT: - - cidx = card->nlogcontr; - if (cidx >= card->nr_controllers) { - printk(KERN_ERR "%s: card with %d controllers ??\n", - card->name, cidx + 1); - break; - } - card->nlogcontr++; - cinfo = &card->ctrlinfo[cidx]; - ctrl = &cinfo->capi_ctrl; - cinfo->versionlen = _get_slice(&p, cinfo->versionbuf); - b1_parse_version(cinfo); - printk(KERN_INFO "%s: %s-card (%s) now active\n", - card->name, - cinfo->version[VER_CARDTYPE], - cinfo->version[VER_DRIVER]); - capi_ctr_ready(&cinfo->capi_ctrl); - break; - - case RECEIVE_TASK_READY: - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: task %d \"%s\" ready.\n", - card->name, ApplId, card->msgbuf); - break; - - case RECEIVE_DEBUGMSG: - MsgLen = _get_slice(&p, card->msgbuf); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); - break; - - default: - printk(KERN_ERR "%s: c4_interrupt: 0x%x ???\n", - card->name, b1cmd); - return; - } -} - -/* ------------------------------------------------------------- */ - -static irqreturn_t c4_handle_interrupt(avmcard *card) -{ - unsigned long flags; - u32 status; - - spin_lock_irqsave(&card->lock, flags); - status = c4inmeml(card->mbase + DOORBELL); - - if (status & DBELL_RESET_HOST) { - u_int i; - c4outmeml(card->mbase + PCI_OUT_INT_MASK, 0x0c); - spin_unlock_irqrestore(&card->lock, flags); - if (card->nlogcontr == 0) - return IRQ_HANDLED; - printk(KERN_ERR "%s: unexpected reset\n", card->name); - for (i = 0; i < card->nr_controllers; i++) { - avmctrl_info *cinfo = &card->ctrlinfo[i]; - memset(cinfo->version, 0, sizeof(cinfo->version)); - spin_lock_irqsave(&card->lock, flags); - capilib_release(&cinfo->ncci_head); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_down(&cinfo->capi_ctrl); - } - card->nlogcontr = 0; - return IRQ_HANDLED; - } - - status &= (DBELL_UP_HOST | DBELL_DOWN_HOST); - if (!status) { - spin_unlock_irqrestore(&card->lock, flags); - return IRQ_HANDLED; - } - c4outmeml(card->mbase + DOORBELL, status); - - if ((status & DBELL_UP_HOST) != 0) { - card->dma->recvlen = c4inmeml(card->mbase + MBOX_UP_LEN); - c4outmeml(card->mbase + MBOX_UP_LEN, 0); - c4_handle_rx(card); - card->dma->recvlen = 0; - c4outmeml(card->mbase + MBOX_UP_LEN, card->dma->recvbuf.size); - c4outmeml(card->mbase + DOORBELL, DBELL_UP_ARM); - } - - if ((status & DBELL_DOWN_HOST) != 0) { - card->csr &= ~DBELL_DOWN_ARM; - c4_dispatch_tx(card); - } else if (card->csr & DBELL_DOWN_HOST) { - if (c4inmeml(card->mbase + MBOX_DOWN_LEN) == 0) { - card->csr &= ~DBELL_DOWN_ARM; - c4_dispatch_tx(card); - } - } - spin_unlock_irqrestore(&card->lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t c4_interrupt(int interrupt, void *devptr) -{ - avmcard *card = devptr; - - return c4_handle_interrupt(card); -} - -/* ------------------------------------------------------------- */ - -static void c4_send_init(avmcard *card) -{ - struct sk_buff *skb; - void *p; - unsigned long flags; - - skb = alloc_skb(15, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost register appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_INIT); - _put_word(&p, CAPI_MAXAPPL); - _put_word(&p, AVM_NCCI_PER_CHANNEL * 30); - _put_word(&p, card->cardnr - 1); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - spin_lock_irqsave(&card->lock, flags); - c4_dispatch_tx(card); - spin_unlock_irqrestore(&card->lock, flags); -} - -static int queue_sendconfigword(avmcard *card, u32 val) -{ - struct sk_buff *skb; - unsigned long flags; - void *p; - - skb = alloc_skb(3 + 4, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, send config\n", - card->name); - return -ENOMEM; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_CONFIG); - _put_word(&p, val); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - spin_lock_irqsave(&card->lock, flags); - c4_dispatch_tx(card); - spin_unlock_irqrestore(&card->lock, flags); - return 0; -} - -static int queue_sendconfig(avmcard *card, char cval[4]) -{ - struct sk_buff *skb; - unsigned long flags; - void *p; - - skb = alloc_skb(3 + 4, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, send config\n", - card->name); - return -ENOMEM; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_CONFIG); - _put_byte(&p, cval[0]); - _put_byte(&p, cval[1]); - _put_byte(&p, cval[2]); - _put_byte(&p, cval[3]); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - - spin_lock_irqsave(&card->lock, flags); - c4_dispatch_tx(card); - spin_unlock_irqrestore(&card->lock, flags); - return 0; -} - -static int c4_send_config(avmcard *card, capiloaddatapart *config) -{ - u8 val[4]; - unsigned char *dp; - u_int left; - int retval; - - if ((retval = queue_sendconfigword(card, 1)) != 0) - return retval; - if ((retval = queue_sendconfigword(card, config->len)) != 0) - return retval; - - dp = config->data; - left = config->len; - while (left >= sizeof(u32)) { - if (config->user) { - if (copy_from_user(val, dp, sizeof(val))) - return -EFAULT; - } else { - memcpy(val, dp, sizeof(val)); - } - if ((retval = queue_sendconfig(card, val)) != 0) - return retval; - left -= sizeof(val); - dp += sizeof(val); - } - if (left) { - memset(val, 0, sizeof(val)); - if (config->user) { - if (copy_from_user(&val, dp, left)) - return -EFAULT; - } else { - memcpy(&val, dp, left); - } - if ((retval = queue_sendconfig(card, val)) != 0) - return retval; - } - - return 0; -} - -static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - int retval; - - if ((retval = c4_load_t4file(card, &data->firmware))) { - printk(KERN_ERR "%s: failed to load t4file!!\n", - card->name); - c4_reset(card); - return retval; - } - - card->csr = 0; - c4outmeml(card->mbase + MBOX_UP_LEN, 0); - c4outmeml(card->mbase + MBOX_DOWN_LEN, 0); - c4outmeml(card->mbase + DOORBELL, DBELL_INIT); - mdelay(1); - c4outmeml(card->mbase + DOORBELL, - DBELL_UP_HOST | DBELL_DOWN_HOST | DBELL_RESET_HOST); - - c4outmeml(card->mbase + PCI_OUT_INT_MASK, 0x08); - - card->dma->recvlen = 0; - c4outmeml(card->mbase + MBOX_UP_ADDR, card->dma->recvbuf.dmaaddr); - c4outmeml(card->mbase + MBOX_UP_LEN, card->dma->recvbuf.size); - c4outmeml(card->mbase + DOORBELL, DBELL_UP_ARM); - - if (data->configuration.len > 0 && data->configuration.data) { - retval = c4_send_config(card, &data->configuration); - if (retval) { - printk(KERN_ERR "%s: failed to set config!!\n", - card->name); - c4_reset(card); - return retval; - } - } - - c4_send_init(card); - - return 0; -} - - -static void c4_reset_ctr(struct capi_ctr *ctrl) -{ - avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card; - avmctrl_info *cinfo; - u_int i; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - - c4_reset(card); - - spin_unlock_irqrestore(&card->lock, flags); - - for (i = 0; i < card->nr_controllers; i++) { - cinfo = &card->ctrlinfo[i]; - memset(cinfo->version, 0, sizeof(cinfo->version)); - capi_ctr_down(&cinfo->capi_ctrl); - } - card->nlogcontr = 0; -} - -static void c4_remove(struct pci_dev *pdev) -{ - avmcard *card = pci_get_drvdata(pdev); - avmctrl_info *cinfo; - u_int i; - - if (!card) - return; - - c4_reset(card); - - for (i = 0; i < card->nr_controllers; i++) { - cinfo = &card->ctrlinfo[i]; - detach_capi_ctr(&cinfo->capi_ctrl); - } - - free_irq(card->irq, card); - iounmap(card->mbase); - release_region(card->port, AVMB1_PORTLEN); - avmcard_dma_free(card->dma); - pci_set_drvdata(pdev, NULL); - b1_free_card(card); -} - -/* ------------------------------------------------------------- */ - - -static void c4_register_appl(struct capi_ctr *ctrl, - u16 appl, - capi_register_params *rp) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - struct sk_buff *skb; - int want = rp->level3cnt; - unsigned long flags; - int nconn; - void *p; - - if (ctrl->cnr == card->cardnr) { - - if (want > 0) nconn = want; - else nconn = ctrl->profile.nbchannel * 4 * -want; - if (nconn == 0) nconn = ctrl->profile.nbchannel * 4; - - skb = alloc_skb(23, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost register appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_REGISTER); - _put_word(&p, appl); - _put_word(&p, 1024 * (nconn + 1)); - _put_word(&p, nconn); - _put_word(&p, rp->datablkcnt); - _put_word(&p, rp->datablklen); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - - spin_lock_irqsave(&card->lock, flags); - c4_dispatch_tx(card); - spin_unlock_irqrestore(&card->lock, flags); - } -} - -/* ------------------------------------------------------------- */ - -static void c4_release_appl(struct capi_ctr *ctrl, u16 appl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned long flags; - struct sk_buff *skb; - void *p; - - spin_lock_irqsave(&card->lock, flags); - capilib_release_appl(&cinfo->ncci_head, appl); - spin_unlock_irqrestore(&card->lock, flags); - - if (ctrl->cnr == card->cardnr) { - skb = alloc_skb(7, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost release appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_RELEASE); - _put_word(&p, appl); - - skb_put(skb, (u8 *)p - (u8 *)skb->data); - skb_queue_tail(&card->dma->send_queue, skb); - spin_lock_irqsave(&card->lock, flags); - c4_dispatch_tx(card); - spin_unlock_irqrestore(&card->lock, flags); - } -} - -/* ------------------------------------------------------------- */ - - -static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - u16 retval = CAPI_NOERROR; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) { - retval = capilib_data_b3_req(&cinfo->ncci_head, - CAPIMSG_APPID(skb->data), - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - } - if (retval == CAPI_NOERROR) { - skb_queue_tail(&card->dma->send_queue, skb); - c4_dispatch_tx(card); - } - spin_unlock_irqrestore(&card->lock, flags); - return retval; -} - -/* ------------------------------------------------------------- */ - -static char *c4_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->membase : 0 - ); - return cinfo->infobuf; -} - -static int c4_proc_show(struct seq_file *m, void *v) -{ - struct capi_ctr *ctrl = m->private; - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - u8 flag; - char *s; - - seq_printf(m, "%-16s %s\n", "name", card->name); - seq_printf(m, "%-16s 0x%x\n", "io", card->port); - seq_printf(m, "%-16s %d\n", "irq", card->irq); - seq_printf(m, "%-16s 0x%lx\n", "membase", card->membase); - switch (card->cardtype) { - case avm_b1isa: s = "B1 ISA"; break; - case avm_b1pci: s = "B1 PCI"; break; - case avm_b1pcmcia: s = "B1 PCMCIA"; break; - case avm_m1: s = "M1"; break; - case avm_m2: s = "M2"; break; - case avm_t1isa: s = "T1 ISA (HEMA)"; break; - case avm_t1pci: s = "T1 PCI"; break; - case avm_c4: s = "C4"; break; - case avm_c2: s = "C2"; break; - default: s = "???"; break; - } - seq_printf(m, "%-16s %s\n", "type", s); - if ((s = cinfo->version[VER_DRIVER]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_driver", s); - if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_cardtype", s); - if ((s = cinfo->version[VER_SERIAL]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_serial", s); - - if (card->cardtype != avm_m1) { - flag = ((u8 *)(ctrl->profile.manu))[3]; - if (flag) - seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", - "protocol", - (flag & 0x01) ? " DSS1" : "", - (flag & 0x02) ? " CT1" : "", - (flag & 0x04) ? " VN3" : "", - (flag & 0x08) ? " NI1" : "", - (flag & 0x10) ? " AUSTEL" : "", - (flag & 0x20) ? " ESS" : "", - (flag & 0x40) ? " 1TR6" : "" - ); - } - if (card->cardtype != avm_m1) { - flag = ((u8 *)(ctrl->profile.manu))[5]; - if (flag) - seq_printf(m, "%-16s%s%s%s%s\n", - "linetype", - (flag & 0x01) ? " point to point" : "", - (flag & 0x02) ? " point to multipoint" : "", - (flag & 0x08) ? " leased line without D-channel" : "", - (flag & 0x04) ? " leased line with D-channel" : "" - ); - } - seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); - - return 0; -} - -/* ------------------------------------------------------------- */ - -static int c4_add_card(struct capicardparams *p, struct pci_dev *dev, - int nr_controllers) -{ - avmcard *card; - avmctrl_info *cinfo; - int retval; - int i; - - card = b1_alloc_card(nr_controllers); - if (!card) { - printk(KERN_WARNING "c4: no memory.\n"); - retval = -ENOMEM; - goto err; - } - card->dma = avmcard_dma_alloc("c4", dev, 2048 + 128, 2048 + 128); - if (!card->dma) { - printk(KERN_WARNING "c4: no memory.\n"); - retval = -ENOMEM; - goto err_free; - } - - sprintf(card->name, "c%d-%x", nr_controllers, p->port); - card->port = p->port; - card->irq = p->irq; - card->membase = p->membase; - card->cardtype = (nr_controllers == 4) ? avm_c4 : avm_c2; - - if (!request_region(card->port, AVMB1_PORTLEN, card->name)) { - printk(KERN_WARNING "c4: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); - retval = -EBUSY; - goto err_free_dma; - } - - card->mbase = ioremap(card->membase, 128); - if (card->mbase == NULL) { - printk(KERN_NOTICE "c4: can't remap memory at 0x%lx\n", - card->membase); - retval = -EIO; - goto err_release_region; - } - - retval = c4_detect(card); - if (retval != 0) { - printk(KERN_NOTICE "c4: NO card at 0x%x error(%d)\n", - card->port, retval); - retval = -EIO; - goto err_unmap; - } - c4_reset(card); - - retval = request_irq(card->irq, c4_interrupt, IRQF_SHARED, card->name, card); - if (retval) { - printk(KERN_ERR "c4: unable to get IRQ %d.\n", card->irq); - retval = -EBUSY; - goto err_unmap; - } - - for (i = 0; i < nr_controllers; i++) { - cinfo = &card->ctrlinfo[i]; - cinfo->capi_ctrl.owner = THIS_MODULE; - cinfo->capi_ctrl.driver_name = "c4"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = c4_register_appl; - cinfo->capi_ctrl.release_appl = c4_release_appl; - cinfo->capi_ctrl.send_message = c4_send_message; - cinfo->capi_ctrl.load_firmware = c4_load_firmware; - cinfo->capi_ctrl.reset_ctr = c4_reset_ctr; - cinfo->capi_ctrl.procinfo = c4_procinfo; - cinfo->capi_ctrl.proc_show = c4_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_ERR "c4: attach controller failed (%d).\n", i); - for (i--; i >= 0; i--) { - cinfo = &card->ctrlinfo[i]; - detach_capi_ctr(&cinfo->capi_ctrl); - } - goto err_free_irq; - } - if (i == 0) - card->cardnr = cinfo->capi_ctrl.cnr; - } - - printk(KERN_INFO "c4: AVM C%d at i/o %#x, irq %d, mem %#lx\n", - nr_controllers, card->port, card->irq, - card->membase); - pci_set_drvdata(dev, card); - return 0; - -err_free_irq: - free_irq(card->irq, card); -err_unmap: - iounmap(card->mbase); -err_release_region: - release_region(card->port, AVMB1_PORTLEN); -err_free_dma: - avmcard_dma_free(card->dma); -err_free: - b1_free_card(card); -err: - return retval; -} - -/* ------------------------------------------------------------- */ - -static int c4_probe(struct pci_dev *dev, const struct pci_device_id *ent) -{ - int nr = ent->driver_data; - int retval = 0; - struct capicardparams param; - - if (pci_enable_device(dev) < 0) { - printk(KERN_ERR "c4: failed to enable AVM-C%d\n", nr); - return -ENODEV; - } - pci_set_master(dev); - - param.port = pci_resource_start(dev, 1); - param.irq = dev->irq; - param.membase = pci_resource_start(dev, 0); - - printk(KERN_INFO "c4: PCI BIOS reports AVM-C%d at i/o %#x, irq %d, mem %#x\n", - nr, param.port, param.irq, param.membase); - - retval = c4_add_card(¶m, dev, nr); - if (retval != 0) { - printk(KERN_ERR "c4: no AVM-C%d at i/o %#x, irq %d detected, mem %#x\n", - nr, param.port, param.irq, param.membase); - pci_disable_device(dev); - return -ENODEV; - } - return 0; -} - -static struct pci_driver c4_pci_driver = { - .name = "c4", - .id_table = c4_pci_tbl, - .probe = c4_probe, - .remove = c4_remove, -}; - -static struct capi_driver capi_driver_c2 = { - .name = "c2", - .revision = "1.0", -}; - -static struct capi_driver capi_driver_c4 = { - .name = "c4", - .revision = "1.0", -}; - -static int __init c4_init(void) -{ - char *p; - char rev[32]; - int err; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, 32); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - err = pci_register_driver(&c4_pci_driver); - if (!err) { - strlcpy(capi_driver_c2.revision, rev, 32); - register_capi_driver(&capi_driver_c2); - strlcpy(capi_driver_c4.revision, rev, 32); - register_capi_driver(&capi_driver_c4); - printk(KERN_INFO "c4: revision %s\n", rev); - } - return err; -} - -static void __exit c4_exit(void) -{ - unregister_capi_driver(&capi_driver_c2); - unregister_capi_driver(&capi_driver_c4); - pci_unregister_driver(&c4_pci_driver); -} - -module_init(c4_init); -module_exit(c4_exit); diff --git a/drivers/staging/isdn/avm/t1isa.c b/drivers/staging/isdn/avm/t1isa.c deleted file mode 100644 index 2153619c5b31..000000000000 --- a/drivers/staging/isdn/avm/t1isa.c +++ /dev/null @@ -1,594 +0,0 @@ -/* $Id: t1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $ - * - * Module for AVM T1 HEMA-card. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" - -/* ------------------------------------------------------------- */ - -static char *revision = "$Revision: 1.1.2.3 $"; - -/* ------------------------------------------------------------- */ - -MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 HEMA ISA card"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------- */ - -static int hema_irq_table[16] = -{0, - 0, - 0, - 0x80, /* irq 3 */ - 0, - 0x90, /* irq 5 */ - 0, - 0xA0, /* irq 7 */ - 0, - 0xB0, /* irq 9 */ - 0xC0, /* irq 10 */ - 0xD0, /* irq 11 */ - 0xE0, /* irq 12 */ - 0, - 0, - 0xF0, /* irq 15 */ -}; - -static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr) -{ - unsigned char cregs[8]; - unsigned char reverse_cardnr; - unsigned char dummy; - int i; - - reverse_cardnr = ((cardnr & 0x01) << 3) | ((cardnr & 0x02) << 1) - | ((cardnr & 0x04) >> 1) | ((cardnr & 0x08) >> 3); - cregs[0] = (HEMA_VERSION_ID << 4) | (reverse_cardnr & 0xf); - cregs[1] = 0x00; /* fast & slow link connected to CON1 */ - cregs[2] = 0x05; /* fast link 20MBit, slow link 20 MBit */ - cregs[3] = 0; - cregs[4] = 0x11; /* zero wait state */ - cregs[5] = hema_irq_table[irq & 0xf]; - cregs[6] = 0; - cregs[7] = 0; - - /* - * no one else should use the ISA bus in this moment, - * but no function there to prevent this :-( - * save_flags(flags); cli(); - */ - - /* board reset */ - t1outp(base, T1_RESETBOARD, 0xf); - mdelay(100); - dummy = t1inp(base, T1_FASTLINK + T1_OUTSTAT); /* first read */ - - /* write config */ - dummy = (base >> 4) & 0xff; - for (i = 1; i <= 0xf; i++) t1outp(base, i, dummy); - t1outp(base, HEMA_PAL_ID & 0xf, dummy); - t1outp(base, HEMA_PAL_ID >> 4, cregs[0]); - for (i = 1; i < 7; i++) t1outp(base, 0, cregs[i]); - t1outp(base, ((base >> 4)) & 0x3, cregs[7]); - /* restore_flags(flags); */ - - mdelay(100); - t1outp(base, T1_FASTLINK + T1_RESETLINK, 0); - t1outp(base, T1_SLOWLINK + T1_RESETLINK, 0); - mdelay(10); - t1outp(base, T1_FASTLINK + T1_RESETLINK, 1); - t1outp(base, T1_SLOWLINK + T1_RESETLINK, 1); - mdelay(100); - t1outp(base, T1_FASTLINK + T1_RESETLINK, 0); - t1outp(base, T1_SLOWLINK + T1_RESETLINK, 0); - mdelay(10); - t1outp(base, T1_FASTLINK + T1_ANALYSE, 0); - mdelay(5); - t1outp(base, T1_SLOWLINK + T1_ANALYSE, 0); - - if (t1inp(base, T1_FASTLINK + T1_OUTSTAT) != 0x1) /* tx empty */ - return 1; - if (t1inp(base, T1_FASTLINK + T1_INSTAT) != 0x0) /* rx empty */ - return 2; - if (t1inp(base, T1_FASTLINK + T1_IRQENABLE) != 0x0) - return 3; - if ((t1inp(base, T1_FASTLINK + T1_FIFOSTAT) & 0xf0) != 0x70) - return 4; - if ((t1inp(base, T1_FASTLINK + T1_IRQMASTER) & 0x0e) != 0) - return 5; - if ((t1inp(base, T1_FASTLINK + T1_IDENT) & 0x7d) != 1) - return 6; - if (t1inp(base, T1_SLOWLINK + T1_OUTSTAT) != 0x1) /* tx empty */ - return 7; - if ((t1inp(base, T1_SLOWLINK + T1_IRQMASTER) & 0x0e) != 0) - return 8; - if ((t1inp(base, T1_SLOWLINK + T1_IDENT) & 0x7d) != 0) - return 9; - return 0; -} - -static irqreturn_t t1isa_interrupt(int interrupt, void *devptr) -{ - avmcard *card = devptr; - avmctrl_info *cinfo = &card->ctrlinfo[0]; - struct capi_ctr *ctrl = &cinfo->capi_ctrl; - unsigned char b1cmd; - struct sk_buff *skb; - - unsigned ApplId; - unsigned MsgLen; - unsigned DataB3Len; - unsigned NCCI; - unsigned WindowSize; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - - while (b1_rx_full(card->port)) { - - b1cmd = b1_get_byte(card->port); - - switch (b1cmd) { - - case RECEIVE_DATA_B3_IND: - - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = t1_get_slice(card->port, card->msgbuf); - DataB3Len = t1_get_slice(card->port, card->databuf); - spin_unlock_irqrestore(&card->lock, flags); - - if (MsgLen < 30) { /* not CAPI 64Bit */ - memset(card->msgbuf + MsgLen, 0, 30 - MsgLen); - MsgLen = 30; - CAPIMSG_SETLEN(card->msgbuf, 30); - } - if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - skb_put_data(skb, card->databuf, DataB3Len); - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_MESSAGE: - - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = t1_get_slice(card->port, card->msgbuf); - if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3) - capilib_data_b3_conf(&cinfo->ncci_head, ApplId, - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_NEW_NCCI: - - ApplId = b1_get_word(card->port); - NCCI = b1_get_word(card->port); - WindowSize = b1_get_word(card->port); - capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize); - spin_unlock_irqrestore(&card->lock, flags); - break; - - case RECEIVE_FREE_NCCI: - - ApplId = b1_get_word(card->port); - NCCI = b1_get_word(card->port); - if (NCCI != 0xffffffff) - capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI); - spin_unlock_irqrestore(&card->lock, flags); - break; - - case RECEIVE_START: - b1_put_byte(card->port, SEND_POLLACK); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_resume_output(ctrl); - break; - - case RECEIVE_STOP: - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_suspend_output(ctrl); - break; - - case RECEIVE_INIT: - - cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf); - spin_unlock_irqrestore(&card->lock, flags); - b1_parse_version(cinfo); - printk(KERN_INFO "%s: %s-card (%s) now active\n", - card->name, - cinfo->version[VER_CARDTYPE], - cinfo->version[VER_DRIVER]); - capi_ctr_ready(ctrl); - break; - - case RECEIVE_TASK_READY: - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = t1_get_slice(card->port, card->msgbuf); - spin_unlock_irqrestore(&card->lock, flags); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: task %d \"%s\" ready.\n", - card->name, ApplId, card->msgbuf); - break; - - case RECEIVE_DEBUGMSG: - MsgLen = t1_get_slice(card->port, card->msgbuf); - spin_unlock_irqrestore(&card->lock, flags); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); - break; - - - case 0xff: - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_ERR "%s: card reseted ?\n", card->name); - return IRQ_HANDLED; - default: - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n", - card->name, b1cmd); - return IRQ_NONE; - } - } - return IRQ_HANDLED; -} - -/* ------------------------------------------------------------- */ - -static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - int retval; - - t1_disable_irq(port); - b1_reset(port); - - if ((retval = b1_load_t4file(card, &data->firmware))) { - b1_reset(port); - printk(KERN_ERR "%s: failed to load t4file!!\n", - card->name); - return retval; - } - - if (data->configuration.len > 0 && data->configuration.data) { - if ((retval = b1_load_config(card, &data->configuration))) { - b1_reset(port); - printk(KERN_ERR "%s: failed to load config!!\n", - card->name); - return retval; - } - } - - if (!b1_loaded(card)) { - printk(KERN_ERR "%s: failed to load t4file.\n", card->name); - return -EIO; - } - - spin_lock_irqsave(&card->lock, flags); - b1_setinterrupt(port, card->irq, card->cardtype); - b1_put_byte(port, SEND_INIT); - b1_put_word(port, CAPI_MAXAPPL); - b1_put_word(port, AVM_NCCI_PER_CHANNEL * 30); - b1_put_word(port, ctrl->cnr - 1); - spin_unlock_irqrestore(&card->lock, flags); - - return 0; -} - -static void t1isa_reset_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - - t1_disable_irq(port); - b1_reset(port); - b1_reset(port); - - memset(cinfo->version, 0, sizeof(cinfo->version)); - spin_lock_irqsave(&card->lock, flags); - capilib_release(&cinfo->ncci_head); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_down(ctrl); -} - -static void t1isa_remove(struct pci_dev *pdev) -{ - avmctrl_info *cinfo = pci_get_drvdata(pdev); - avmcard *card; - - if (!cinfo) - return; - - card = cinfo->card; - - t1_disable_irq(card->port); - b1_reset(card->port); - b1_reset(card->port); - t1_reset(card->port); - - detach_capi_ctr(&cinfo->capi_ctrl); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - b1_free_card(card); -} - -/* ------------------------------------------------------------- */ - -static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); -static char *t1isa_procinfo(struct capi_ctr *ctrl); - -static int t1isa_probe(struct pci_dev *pdev, int cardnr) -{ - avmctrl_info *cinfo; - avmcard *card; - int retval; - - card = b1_alloc_card(1); - if (!card) { - printk(KERN_WARNING "t1isa: no memory.\n"); - retval = -ENOMEM; - goto err; - } - - cinfo = card->ctrlinfo; - card->port = pci_resource_start(pdev, 0); - card->irq = pdev->irq; - card->cardtype = avm_t1isa; - card->cardnr = cardnr; - sprintf(card->name, "t1isa-%x", card->port); - - if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) { - printk(KERN_WARNING "t1isa: invalid port 0x%x.\n", card->port); - retval = -EINVAL; - goto err_free; - } - if (hema_irq_table[card->irq & 0xf] == 0) { - printk(KERN_WARNING "t1isa: irq %d not valid.\n", card->irq); - retval = -EINVAL; - goto err_free; - } - if (!request_region(card->port, AVMB1_PORTLEN, card->name)) { - printk(KERN_INFO "t1isa: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); - retval = -EBUSY; - goto err_free; - } - retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card); - if (retval) { - printk(KERN_INFO "t1isa: unable to get IRQ %d.\n", card->irq); - retval = -EBUSY; - goto err_release_region; - } - - if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) { - printk(KERN_INFO "t1isa: NO card at 0x%x (%d)\n", - card->port, retval); - retval = -ENODEV; - goto err_free_irq; - } - t1_disable_irq(card->port); - b1_reset(card->port); - - cinfo->capi_ctrl.owner = THIS_MODULE; - cinfo->capi_ctrl.driver_name = "t1isa"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = b1_register_appl; - cinfo->capi_ctrl.release_appl = b1_release_appl; - cinfo->capi_ctrl.send_message = t1isa_send_message; - cinfo->capi_ctrl.load_firmware = t1isa_load_firmware; - cinfo->capi_ctrl.reset_ctr = t1isa_reset_ctr; - cinfo->capi_ctrl.procinfo = t1isa_procinfo; - cinfo->capi_ctrl.proc_show = b1_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_INFO "t1isa: attach controller failed.\n"); - goto err_free_irq; - } - - printk(KERN_INFO "t1isa: AVM T1 ISA at i/o %#x, irq %d, card %d\n", - card->port, card->irq, card->cardnr); - - pci_set_drvdata(pdev, cinfo); - return 0; - -err_free_irq: - free_irq(card->irq, card); -err_release_region: - release_region(card->port, AVMB1_PORTLEN); -err_free: - b1_free_card(card); -err: - return retval; -} - -static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - u16 len = CAPIMSG_LEN(skb->data); - u8 cmd = CAPIMSG_COMMAND(skb->data); - u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data); - u16 dlen, retval; - - spin_lock_irqsave(&card->lock, flags); - if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { - retval = capilib_data_b3_req(&cinfo->ncci_head, - CAPIMSG_APPID(skb->data), - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - if (retval != CAPI_NOERROR) { - spin_unlock_irqrestore(&card->lock, flags); - return retval; - } - dlen = CAPIMSG_DATALEN(skb->data); - - b1_put_byte(port, SEND_DATA_B3_REQ); - t1_put_slice(port, skb->data, len); - t1_put_slice(port, skb->data + len, dlen); - } else { - b1_put_byte(port, SEND_MESSAGE); - t1_put_slice(port, skb->data, len); - } - spin_unlock_irqrestore(&card->lock, flags); - dev_kfree_skb_any(skb); - return CAPI_NOERROR; -} -/* ------------------------------------------------------------- */ - -static char *t1isa_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d %d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->cardnr : 0 - ); - return cinfo->infobuf; -} - - -/* ------------------------------------------------------------- */ - -#define MAX_CARDS 4 -static struct pci_dev isa_dev[MAX_CARDS]; -static int io[MAX_CARDS]; -static int irq[MAX_CARDS]; -static int cardnr[MAX_CARDS]; - -module_param_hw_array(io, int, ioport, NULL, 0); -module_param_hw_array(irq, int, irq, NULL, 0); -module_param_array(cardnr, int, NULL, 0); -MODULE_PARM_DESC(io, "I/O base address(es)"); -MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); -MODULE_PARM_DESC(cardnr, "Card number(s) (as jumpered)"); - -static int t1isa_add_card(struct capi_driver *driver, capicardparams *data) -{ - int i; - - for (i = 0; i < MAX_CARDS; i++) { - if (isa_dev[i].resource[0].start) - continue; - - isa_dev[i].resource[0].start = data->port; - isa_dev[i].irq = data->irq; - - if (t1isa_probe(&isa_dev[i], data->cardnr) == 0) - return 0; - } - return -ENODEV; -} - -static struct capi_driver capi_driver_t1isa = { - .name = "t1isa", - .revision = "1.0", - .add_card = t1isa_add_card, -}; - -static int __init t1isa_init(void) -{ - char rev[32]; - char *p; - int i; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, 32); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - for (i = 0; i < MAX_CARDS; i++) { - if (!io[i]) - break; - - isa_dev[i].resource[0].start = io[i]; - isa_dev[i].irq = irq[i]; - - if (t1isa_probe(&isa_dev[i], cardnr[i]) != 0) - return -ENODEV; - } - - strlcpy(capi_driver_t1isa.revision, rev, 32); - register_capi_driver(&capi_driver_t1isa); - printk(KERN_INFO "t1isa: revision %s\n", rev); - - return 0; -} - -static void __exit t1isa_exit(void) -{ - int i; - - unregister_capi_driver(&capi_driver_t1isa); - for (i = 0; i < MAX_CARDS; i++) { - if (!io[i]) - break; - - t1isa_remove(&isa_dev[i]); - } -} - -module_init(t1isa_init); -module_exit(t1isa_exit); diff --git a/drivers/staging/isdn/avm/t1pci.c b/drivers/staging/isdn/avm/t1pci.c deleted file mode 100644 index f5ed1d5004c9..000000000000 --- a/drivers/staging/isdn/avm/t1pci.c +++ /dev/null @@ -1,259 +0,0 @@ -/* $Id: t1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ - * - * Module for AVM T1 PCI-card. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" - -#undef CONFIG_T1PCI_DEBUG -#undef CONFIG_T1PCI_POLLDEBUG - -/* ------------------------------------------------------------- */ -static char *revision = "$Revision: 1.1.2.2 $"; -/* ------------------------------------------------------------- */ - -static struct pci_device_id t1pci_pci_tbl[] = { - { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, PCI_ANY_ID, PCI_ANY_ID }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(pci, t1pci_pci_tbl); -MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 PCI card"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------- */ - -static char *t1pci_procinfo(struct capi_ctr *ctrl); - -static int t1pci_add_card(struct capicardparams *p, struct pci_dev *pdev) -{ - avmcard *card; - avmctrl_info *cinfo; - int retval; - - card = b1_alloc_card(1); - if (!card) { - printk(KERN_WARNING "t1pci: no memory.\n"); - retval = -ENOMEM; - goto err; - } - - card->dma = avmcard_dma_alloc("t1pci", pdev, 2048 + 128, 2048 + 128); - if (!card->dma) { - printk(KERN_WARNING "t1pci: no memory.\n"); - retval = -ENOMEM; - goto err_free; - } - - cinfo = card->ctrlinfo; - sprintf(card->name, "t1pci-%x", p->port); - card->port = p->port; - card->irq = p->irq; - card->membase = p->membase; - card->cardtype = avm_t1pci; - - if (!request_region(card->port, AVMB1_PORTLEN, card->name)) { - printk(KERN_WARNING "t1pci: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); - retval = -EBUSY; - goto err_free_dma; - } - - card->mbase = ioremap(card->membase, 64); - if (!card->mbase) { - printk(KERN_NOTICE "t1pci: can't remap memory at 0x%lx\n", - card->membase); - retval = -EIO; - goto err_release_region; - } - - b1dma_reset(card); - - retval = t1pci_detect(card); - if (retval != 0) { - if (retval < 6) - printk(KERN_NOTICE "t1pci: NO card at 0x%x (%d)\n", - card->port, retval); - else - printk(KERN_NOTICE "t1pci: card at 0x%x, but cable not connected or T1 has no power (%d)\n", - card->port, retval); - retval = -EIO; - goto err_unmap; - } - b1dma_reset(card); - - retval = request_irq(card->irq, b1dma_interrupt, IRQF_SHARED, card->name, card); - if (retval) { - printk(KERN_ERR "t1pci: unable to get IRQ %d.\n", card->irq); - retval = -EBUSY; - goto err_unmap; - } - - cinfo->capi_ctrl.owner = THIS_MODULE; - cinfo->capi_ctrl.driver_name = "t1pci"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = b1dma_register_appl; - cinfo->capi_ctrl.release_appl = b1dma_release_appl; - cinfo->capi_ctrl.send_message = b1dma_send_message; - cinfo->capi_ctrl.load_firmware = b1dma_load_firmware; - cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr; - cinfo->capi_ctrl.procinfo = t1pci_procinfo; - cinfo->capi_ctrl.proc_show = b1dma_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_ERR "t1pci: attach controller failed.\n"); - retval = -EBUSY; - goto err_free_irq; - } - card->cardnr = cinfo->capi_ctrl.cnr; - - printk(KERN_INFO "t1pci: AVM T1 PCI at i/o %#x, irq %d, mem %#lx\n", - card->port, card->irq, card->membase); - - pci_set_drvdata(pdev, card); - return 0; - -err_free_irq: - free_irq(card->irq, card); -err_unmap: - iounmap(card->mbase); -err_release_region: - release_region(card->port, AVMB1_PORTLEN); -err_free_dma: - avmcard_dma_free(card->dma); -err_free: - b1_free_card(card); -err: - return retval; -} - -/* ------------------------------------------------------------- */ - -static void t1pci_remove(struct pci_dev *pdev) -{ - avmcard *card = pci_get_drvdata(pdev); - avmctrl_info *cinfo = card->ctrlinfo; - - b1dma_reset(card); - - detach_capi_ctr(&cinfo->capi_ctrl); - free_irq(card->irq, card); - iounmap(card->mbase); - release_region(card->port, AVMB1_PORTLEN); - avmcard_dma_free(card->dma); - b1_free_card(card); -} - -/* ------------------------------------------------------------- */ - -static char *t1pci_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->membase : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -static int t1pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) -{ - struct capicardparams param; - int retval; - - if (pci_enable_device(dev) < 0) { - printk(KERN_ERR "t1pci: failed to enable AVM-T1-PCI\n"); - return -ENODEV; - } - pci_set_master(dev); - - param.port = pci_resource_start(dev, 1); - param.irq = dev->irq; - param.membase = pci_resource_start(dev, 0); - - printk(KERN_INFO "t1pci: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n", - param.port, param.irq, param.membase); - - retval = t1pci_add_card(¶m, dev); - if (retval != 0) { - printk(KERN_ERR "t1pci: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n", - param.port, param.irq, param.membase); - pci_disable_device(dev); - return -ENODEV; - } - return 0; -} - -static struct pci_driver t1pci_pci_driver = { - .name = "t1pci", - .id_table = t1pci_pci_tbl, - .probe = t1pci_probe, - .remove = t1pci_remove, -}; - -static struct capi_driver capi_driver_t1pci = { - .name = "t1pci", - .revision = "1.0", -}; - -static int __init t1pci_init(void) -{ - char *p; - char rev[32]; - int err; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, 32); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - err = pci_register_driver(&t1pci_pci_driver); - if (!err) { - strlcpy(capi_driver_t1pci.revision, rev, 32); - register_capi_driver(&capi_driver_t1pci); - printk(KERN_INFO "t1pci: revision %s\n", rev); - } - return err; -} - -static void __exit t1pci_exit(void) -{ - unregister_capi_driver(&capi_driver_t1pci); - pci_unregister_driver(&t1pci_pci_driver); -} - -module_init(t1pci_init); -module_exit(t1pci_exit); diff --git a/drivers/staging/isdn/gigaset/Kconfig b/drivers/staging/isdn/gigaset/Kconfig deleted file mode 100644 index c593105b3600..000000000000 --- a/drivers/staging/isdn/gigaset/Kconfig +++ /dev/null @@ -1,62 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -menuconfig ISDN_DRV_GIGASET - tristate "Siemens Gigaset support" - depends on TTY - select CRC_CCITT - select BITREVERSE - help - This driver supports the Siemens Gigaset SX205/255 family of - ISDN DECT bases, including the predecessors Gigaset 3070/3075 - and 4170/4175 and their T-Com versions Sinus 45isdn and Sinus - 721X. - If you have one of these devices, say M here and for at least - one of the connection specific parts that follow. - This will build a module called "gigaset". - Note: If you build your ISDN subsystem (ISDN_CAPI or ISDN_I4L) - as a module, you have to build this driver as a module too, - otherwise the Gigaset device won't show up as an ISDN device. - -if ISDN_DRV_GIGASET - -config GIGASET_CAPI - bool "Gigaset CAPI support" - depends on ISDN_CAPI='y'||(ISDN_CAPI='m'&&ISDN_DRV_GIGASET='m') - default 'y' - help - Build the Gigaset driver as a CAPI 2.0 driver interfacing with - the Kernel CAPI subsystem. To use it with the old ISDN4Linux - subsystem you'll have to enable the capidrv glue driver. - (select ISDN_CAPI_CAPIDRV.) - Say N to build the old native ISDN4Linux variant. - If unsure, say Y. - -config GIGASET_BASE - tristate "Gigaset base station support" - depends on USB - help - Say M here if you want to use the USB interface of the Gigaset - base for connection to your system. - This will build a module called "bas_gigaset". - -config GIGASET_M105 - tristate "Gigaset M105 support" - depends on USB - help - Say M here if you want to connect to the Gigaset base via DECT - using a Gigaset M105 (Sinus 45 Data 2) USB DECT device. - This will build a module called "usb_gigaset". - -config GIGASET_M101 - tristate "Gigaset M101 support" - help - Say M here if you want to connect to the Gigaset base via DECT - using a Gigaset M101 (Sinus 45 Data 1) RS232 DECT device. - This will build a module called "ser_gigaset". - -config GIGASET_DEBUG - bool "Gigaset debugging" - help - This enables debugging code in the Gigaset drivers. - If in doubt, say yes. - -endif # ISDN_DRV_GIGASET diff --git a/drivers/staging/isdn/gigaset/Makefile b/drivers/staging/isdn/gigaset/Makefile deleted file mode 100644 index 9c010891dcd7..000000000000 --- a/drivers/staging/isdn/gigaset/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -gigaset-y := common.o interface.o proc.o ev-layer.o asyncdata.o - -ifdef CONFIG_GIGASET_CAPI -gigaset-y += capi.o -else -gigaset-y += dummyll.o -endif - -usb_gigaset-y := usb-gigaset.o -ser_gigaset-y := ser-gigaset.o -bas_gigaset-y := bas-gigaset.o isocdata.o - -obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset.o -obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o -obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o -obj-$(CONFIG_GIGASET_M101) += ser_gigaset.o diff --git a/drivers/staging/isdn/gigaset/asyncdata.c b/drivers/staging/isdn/gigaset/asyncdata.c deleted file mode 100644 index a34b3c9d8a71..000000000000 --- a/drivers/staging/isdn/gigaset/asyncdata.c +++ /dev/null @@ -1,606 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Common data handling layer for ser_gigaset and usb_gigaset - * - * Copyright (c) 2005 by Tilman Schmidt , - * Hansjoerg Lipp , - * Stefan Eilers. - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include -#include - -/* check if byte must be stuffed/escaped - * I'm not sure which data should be encoded. - * Therefore I will go the hard way and encode every value - * less than 0x20, the flag sequence and the control escape char. - */ -static inline int muststuff(unsigned char c) -{ - if (c < PPP_TRANS) return 1; - if (c == PPP_FLAG) return 1; - if (c == PPP_ESCAPE) return 1; - /* other possible candidates: */ - /* 0x91: XON with parity set */ - /* 0x93: XOFF with parity set */ - return 0; -} - -/* == data input =========================================================== */ - -/* process a block of received bytes in command mode - * (mstate != MS_LOCKED && (inputstate & INS_command)) - * Append received bytes to the command response buffer and forward them - * line by line to the response handler. Exit whenever a mode/state change - * might have occurred. - * Note: Received lines may be terminated by CR, LF, or CR LF, which will be - * removed before passing the line to the response handler. - * Return value: - * number of processed bytes - */ -static unsigned cmd_loop(unsigned numbytes, struct inbuf_t *inbuf) -{ - unsigned char *src = inbuf->data + inbuf->head; - struct cardstate *cs = inbuf->cs; - unsigned cbytes = cs->cbytes; - unsigned procbytes = 0; - unsigned char c; - - while (procbytes < numbytes) { - c = *src++; - procbytes++; - - switch (c) { - case '\n': - if (cbytes == 0 && cs->respdata[0] == '\r') { - /* collapse LF with preceding CR */ - cs->respdata[0] = 0; - break; - } - /* fall through */ - case '\r': - /* end of message line, pass to response handler */ - if (cbytes >= MAX_RESP_SIZE) { - dev_warn(cs->dev, "response too large (%d)\n", - cbytes); - cbytes = MAX_RESP_SIZE; - } - cs->cbytes = cbytes; - gigaset_dbg_buffer(DEBUG_TRANSCMD, "received response", - cbytes, cs->respdata); - gigaset_handle_modem_response(cs); - cbytes = 0; - - /* store EOL byte for CRLF collapsing */ - cs->respdata[0] = c; - - /* cs->dle may have changed */ - if (cs->dle && !(inbuf->inputstate & INS_DLE_command)) - inbuf->inputstate &= ~INS_command; - - /* return for reevaluating state */ - goto exit; - - case DLE_FLAG: - if (inbuf->inputstate & INS_DLE_char) { - /* quoted DLE: clear quote flag */ - inbuf->inputstate &= ~INS_DLE_char; - } else if (cs->dle || - (inbuf->inputstate & INS_DLE_command)) { - /* DLE escape, pass up for handling */ - inbuf->inputstate |= INS_DLE_char; - goto exit; - } - /* quoted or not in DLE mode: treat as regular data */ - /* fall through */ - default: - /* append to line buffer if possible */ - if (cbytes < MAX_RESP_SIZE) - cs->respdata[cbytes] = c; - cbytes++; - } - } -exit: - cs->cbytes = cbytes; - return procbytes; -} - -/* process a block of received bytes in lock mode - * All received bytes are passed unmodified to the tty i/f. - * Return value: - * number of processed bytes - */ -static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf) -{ - unsigned char *src = inbuf->data + inbuf->head; - - gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src); - gigaset_if_receive(inbuf->cs, src, numbytes); - return numbytes; -} - -/* process a block of received bytes in HDLC data mode - * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC) - * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. - * When a frame is complete, check the FCS and pass valid frames to the LL. - * If DLE is encountered, return immediately to let the caller handle it. - * Return value: - * number of processed bytes - */ -static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) -{ - struct cardstate *cs = inbuf->cs; - struct bc_state *bcs = cs->bcs; - int inputstate = bcs->inputstate; - __u16 fcs = bcs->rx_fcs; - struct sk_buff *skb = bcs->rx_skb; - unsigned char *src = inbuf->data + inbuf->head; - unsigned procbytes = 0; - unsigned char c; - - if (inputstate & INS_byte_stuff) { - if (!numbytes) - return 0; - inputstate &= ~INS_byte_stuff; - goto byte_stuff; - } - - while (procbytes < numbytes) { - c = *src++; - procbytes++; - if (c == DLE_FLAG) { - if (inputstate & INS_DLE_char) { - /* quoted DLE: clear quote flag */ - inputstate &= ~INS_DLE_char; - } else if (cs->dle || (inputstate & INS_DLE_command)) { - /* DLE escape, pass up for handling */ - inputstate |= INS_DLE_char; - break; - } - } - - if (c == PPP_ESCAPE) { - /* byte stuffing indicator: pull in next byte */ - if (procbytes >= numbytes) { - /* end of buffer, save for later processing */ - inputstate |= INS_byte_stuff; - break; - } -byte_stuff: - c = *src++; - procbytes++; - if (c == DLE_FLAG) { - if (inputstate & INS_DLE_char) { - /* quoted DLE: clear quote flag */ - inputstate &= ~INS_DLE_char; - } else if (cs->dle || - (inputstate & INS_DLE_command)) { - /* DLE escape, pass up for handling */ - inputstate |= - INS_DLE_char | INS_byte_stuff; - break; - } - } - c ^= PPP_TRANS; -#ifdef CONFIG_GIGASET_DEBUG - if (!muststuff(c)) - gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c); -#endif - } else if (c == PPP_FLAG) { - /* end of frame: process content if any */ - if (inputstate & INS_have_data) { - gig_dbg(DEBUG_HDLC, - "7e----------------------------"); - - /* check and pass received frame */ - if (!skb) { - /* skipped frame */ - gigaset_isdn_rcv_err(bcs); - } else if (skb->len < 2) { - /* frame too short for FCS */ - dev_warn(cs->dev, - "short frame (%d)\n", - skb->len); - gigaset_isdn_rcv_err(bcs); - dev_kfree_skb_any(skb); - } else if (fcs != PPP_GOODFCS) { - /* frame check error */ - dev_err(cs->dev, - "Checksum failed, %u bytes corrupted!\n", - skb->len); - gigaset_isdn_rcv_err(bcs); - dev_kfree_skb_any(skb); - } else { - /* good frame */ - __skb_trim(skb, skb->len - 2); - gigaset_skb_rcvd(bcs, skb); - } - - /* prepare reception of next frame */ - inputstate &= ~INS_have_data; - skb = gigaset_new_rx_skb(bcs); - } else { - /* empty frame (7E 7E) */ -#ifdef CONFIG_GIGASET_DEBUG - ++bcs->emptycount; -#endif - if (!skb) { - /* skipped (?) */ - gigaset_isdn_rcv_err(bcs); - skb = gigaset_new_rx_skb(bcs); - } - } - - fcs = PPP_INITFCS; - continue; -#ifdef CONFIG_GIGASET_DEBUG - } else if (muststuff(c)) { - /* Should not happen. Possible after ZDLE=1. */ - gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); -#endif - } - - /* regular data byte, append to skb */ -#ifdef CONFIG_GIGASET_DEBUG - if (!(inputstate & INS_have_data)) { - gig_dbg(DEBUG_HDLC, "7e (%d x) ================", - bcs->emptycount); - bcs->emptycount = 0; - } -#endif - inputstate |= INS_have_data; - if (skb) { - if (skb->len >= bcs->rx_bufsize) { - dev_warn(cs->dev, "received packet too long\n"); - dev_kfree_skb_any(skb); - /* skip remainder of packet */ - bcs->rx_skb = skb = NULL; - } else { - __skb_put_u8(skb, c); - fcs = crc_ccitt_byte(fcs, c); - } - } - } - - bcs->inputstate = inputstate; - bcs->rx_fcs = fcs; - return procbytes; -} - -/* process a block of received bytes in transparent data mode - * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 != L2_HDLC) - * Invert bytes, undoing byte stuffing and watching for DLE escapes. - * If DLE is encountered, return immediately to let the caller handle it. - * Return value: - * number of processed bytes - */ -static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf) -{ - struct cardstate *cs = inbuf->cs; - struct bc_state *bcs = cs->bcs; - int inputstate = bcs->inputstate; - struct sk_buff *skb = bcs->rx_skb; - unsigned char *src = inbuf->data + inbuf->head; - unsigned procbytes = 0; - unsigned char c; - - if (!skb) { - /* skip this block */ - gigaset_new_rx_skb(bcs); - return numbytes; - } - - while (procbytes < numbytes && skb->len < bcs->rx_bufsize) { - c = *src++; - procbytes++; - - if (c == DLE_FLAG) { - if (inputstate & INS_DLE_char) { - /* quoted DLE: clear quote flag */ - inputstate &= ~INS_DLE_char; - } else if (cs->dle || (inputstate & INS_DLE_command)) { - /* DLE escape, pass up for handling */ - inputstate |= INS_DLE_char; - break; - } - } - - /* regular data byte: append to current skb */ - inputstate |= INS_have_data; - __skb_put_u8(skb, bitrev8(c)); - } - - /* pass data up */ - if (inputstate & INS_have_data) { - gigaset_skb_rcvd(bcs, skb); - inputstate &= ~INS_have_data; - gigaset_new_rx_skb(bcs); - } - - bcs->inputstate = inputstate; - return procbytes; -} - -/* process DLE escapes - * Called whenever a DLE sequence might be encountered in the input stream. - * Either processes the entire DLE sequence or, if that isn't possible, - * notes the fact that an initial DLE has been received in the INS_DLE_char - * inputstate flag and resumes processing of the sequence on the next call. - */ -static void handle_dle(struct inbuf_t *inbuf) -{ - struct cardstate *cs = inbuf->cs; - - if (cs->mstate == MS_LOCKED) - return; /* no DLE processing in lock mode */ - - if (!(inbuf->inputstate & INS_DLE_char)) { - /* no DLE pending */ - if (inbuf->data[inbuf->head] == DLE_FLAG && - (cs->dle || inbuf->inputstate & INS_DLE_command)) { - /* start of DLE sequence */ - inbuf->head++; - if (inbuf->head == inbuf->tail || - inbuf->head == RBUFSIZE) { - /* end of buffer, save for later processing */ - inbuf->inputstate |= INS_DLE_char; - return; - } - } else { - /* regular data byte */ - return; - } - } - - /* consume pending DLE */ - inbuf->inputstate &= ~INS_DLE_char; - - switch (inbuf->data[inbuf->head]) { - case 'X': /* begin of event message */ - if (inbuf->inputstate & INS_command) - dev_notice(cs->dev, - "received X in command mode\n"); - inbuf->inputstate |= INS_command | INS_DLE_command; - inbuf->head++; /* byte consumed */ - break; - case '.': /* end of event message */ - if (!(inbuf->inputstate & INS_DLE_command)) - dev_notice(cs->dev, - "received . without X\n"); - inbuf->inputstate &= ~INS_DLE_command; - /* return to data mode if in DLE mode */ - if (cs->dle) - inbuf->inputstate &= ~INS_command; - inbuf->head++; /* byte consumed */ - break; - case DLE_FLAG: /* DLE in data stream */ - /* mark as quoted */ - inbuf->inputstate |= INS_DLE_char; - if (!(cs->dle || inbuf->inputstate & INS_DLE_command)) - dev_notice(cs->dev, - "received not in DLE mode\n"); - break; /* quoted byte left in buffer */ - default: - dev_notice(cs->dev, "received <%02x>\n", - inbuf->data[inbuf->head]); - /* quoted byte left in buffer */ - } -} - -/** - * gigaset_m10x_input() - process a block of data received from the device - * @inbuf: received data and device descriptor structure. - * - * Called by hardware module {ser,usb}_gigaset with a block of received - * bytes. Separates the bytes received over the serial data channel into - * user data and command replies (locked/unlocked) according to the - * current state of the interface. - */ -void gigaset_m10x_input(struct inbuf_t *inbuf) -{ - struct cardstate *cs = inbuf->cs; - unsigned numbytes, procbytes; - - gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", inbuf->head, inbuf->tail); - - while (inbuf->head != inbuf->tail) { - /* check for DLE escape */ - handle_dle(inbuf); - - /* process a contiguous block of bytes */ - numbytes = (inbuf->head > inbuf->tail ? - RBUFSIZE : inbuf->tail) - inbuf->head; - gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); - /* - * numbytes may be 0 if handle_dle() ate the last byte. - * This does no harm, *_loop() will just return 0 immediately. - */ - - if (cs->mstate == MS_LOCKED) - procbytes = lock_loop(numbytes, inbuf); - else if (inbuf->inputstate & INS_command) - procbytes = cmd_loop(numbytes, inbuf); - else if (cs->bcs->proto2 == L2_HDLC) - procbytes = hdlc_loop(numbytes, inbuf); - else - procbytes = iraw_loop(numbytes, inbuf); - inbuf->head += procbytes; - - /* check for buffer wraparound */ - if (inbuf->head >= RBUFSIZE) - inbuf->head = 0; - - gig_dbg(DEBUG_INTR, "head set to %u", inbuf->head); - } -} -EXPORT_SYMBOL_GPL(gigaset_m10x_input); - - -/* == data output ========================================================== */ - -/* - * Encode a data packet into an octet stuffed HDLC frame with FCS, - * opening and closing flags, preserving headroom data. - * parameters: - * skb skb containing original packet (freed upon return) - * Return value: - * pointer to newly allocated skb containing the result frame - * and the original link layer header, NULL on error - */ -static struct sk_buff *HDLC_Encode(struct sk_buff *skb) -{ - struct sk_buff *hdlc_skb; - __u16 fcs; - unsigned char c; - unsigned char *cp; - int len; - unsigned int stuf_cnt; - - stuf_cnt = 0; - fcs = PPP_INITFCS; - cp = skb->data; - len = skb->len; - while (len--) { - if (muststuff(*cp)) - stuf_cnt++; - fcs = crc_ccitt_byte(fcs, *cp++); - } - fcs ^= 0xffff; /* complement */ - - /* size of new buffer: original size + number of stuffing bytes - * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes - * + room for link layer header - */ - hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + skb->mac_len); - if (!hdlc_skb) { - dev_kfree_skb_any(skb); - return NULL; - } - - /* Copy link layer header into new skb */ - skb_reset_mac_header(hdlc_skb); - skb_reserve(hdlc_skb, skb->mac_len); - memcpy(skb_mac_header(hdlc_skb), skb_mac_header(skb), skb->mac_len); - hdlc_skb->mac_len = skb->mac_len; - - /* Add flag sequence in front of everything.. */ - skb_put_u8(hdlc_skb, PPP_FLAG); - - /* Perform byte stuffing while copying data. */ - while (skb->len--) { - if (muststuff(*skb->data)) { - skb_put_u8(hdlc_skb, PPP_ESCAPE); - skb_put_u8(hdlc_skb, (*skb->data++) ^ PPP_TRANS); - } else - skb_put_u8(hdlc_skb, *skb->data++); - } - - /* Finally add FCS (byte stuffed) and flag sequence */ - c = (fcs & 0x00ff); /* least significant byte first */ - if (muststuff(c)) { - skb_put_u8(hdlc_skb, PPP_ESCAPE); - c ^= PPP_TRANS; - } - skb_put_u8(hdlc_skb, c); - - c = ((fcs >> 8) & 0x00ff); - if (muststuff(c)) { - skb_put_u8(hdlc_skb, PPP_ESCAPE); - c ^= PPP_TRANS; - } - skb_put_u8(hdlc_skb, c); - - skb_put_u8(hdlc_skb, PPP_FLAG); - - dev_kfree_skb_any(skb); - return hdlc_skb; -} - -/* - * Encode a data packet into an octet stuffed raw bit inverted frame, - * preserving headroom data. - * parameters: - * skb skb containing original packet (freed upon return) - * Return value: - * pointer to newly allocated skb containing the result frame - * and the original link layer header, NULL on error - */ -static struct sk_buff *iraw_encode(struct sk_buff *skb) -{ - struct sk_buff *iraw_skb; - unsigned char c; - unsigned char *cp; - int len; - - /* size of new buffer (worst case = every byte must be stuffed): - * 2 * original size + room for link layer header - */ - iraw_skb = dev_alloc_skb(2 * skb->len + skb->mac_len); - if (!iraw_skb) { - dev_kfree_skb_any(skb); - return NULL; - } - - /* copy link layer header into new skb */ - skb_reset_mac_header(iraw_skb); - skb_reserve(iraw_skb, skb->mac_len); - memcpy(skb_mac_header(iraw_skb), skb_mac_header(skb), skb->mac_len); - iraw_skb->mac_len = skb->mac_len; - - /* copy and stuff data */ - cp = skb->data; - len = skb->len; - while (len--) { - c = bitrev8(*cp++); - if (c == DLE_FLAG) - skb_put_u8(iraw_skb, c); - skb_put_u8(iraw_skb, c); - } - dev_kfree_skb_any(skb); - return iraw_skb; -} - -/** - * gigaset_m10x_send_skb() - queue an skb for sending - * @bcs: B channel descriptor structure. - * @skb: data to send. - * - * Called by LL to encode and queue an skb for sending, and start - * transmission if necessary. - * Once the payload data has been transmitted completely, gigaset_skb_sent() - * will be called with the skb's link layer header preserved. - * - * Return value: - * number of bytes accepted for sending (skb->len) if ok, - * error code < 0 (eg. -ENOMEM) on error - */ -int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) -{ - struct cardstate *cs = bcs->cs; - unsigned len = skb->len; - unsigned long flags; - - if (bcs->proto2 == L2_HDLC) - skb = HDLC_Encode(skb); - else - skb = iraw_encode(skb); - if (!skb) { - dev_err(cs->dev, - "unable to allocate memory for encoding!\n"); - return -ENOMEM; - } - - skb_queue_tail(&bcs->squeue, skb); - spin_lock_irqsave(&cs->lock, flags); - if (cs->connected) - tasklet_schedule(&cs->write_tasklet); - spin_unlock_irqrestore(&cs->lock, flags); - - return len; /* ok so far */ -} -EXPORT_SYMBOL_GPL(gigaset_m10x_send_skb); diff --git a/drivers/staging/isdn/gigaset/bas-gigaset.c b/drivers/staging/isdn/gigaset/bas-gigaset.c deleted file mode 100644 index c334525a5f63..000000000000 --- a/drivers/staging/isdn/gigaset/bas-gigaset.c +++ /dev/null @@ -1,2672 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * USB driver for Gigaset 307x base via direct USB connection. - * - * Copyright (c) 2001 by Hansjoerg Lipp , - * Tilman Schmidt , - * Stefan Eilers. - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include -#include - -/* Version Information */ -#define DRIVER_AUTHOR "Tilman Schmidt , Hansjoerg Lipp , Stefan Eilers" -#define DRIVER_DESC "USB Driver for Gigaset 307x" - - -/* Module parameters */ - -static int startmode = SM_ISDN; -static int cidmode = 1; - -module_param(startmode, int, S_IRUGO); -module_param(cidmode, int, S_IRUGO); -MODULE_PARM_DESC(startmode, "start in isdn4linux mode"); -MODULE_PARM_DESC(cidmode, "Call-ID mode"); - -#define GIGASET_MINORS 1 -#define GIGASET_MINOR 16 -#define GIGASET_MODULENAME "bas_gigaset" -#define GIGASET_DEVNAME "ttyGB" - -/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */ -#define IF_WRITEBUF 264 - -/* interrupt pipe message size according to ibid. ch. 2.2 */ -#define IP_MSGSIZE 3 - -/* Values for the Gigaset 307x */ -#define USB_GIGA_VENDOR_ID 0x0681 -#define USB_3070_PRODUCT_ID 0x0001 -#define USB_3075_PRODUCT_ID 0x0002 -#define USB_SX303_PRODUCT_ID 0x0021 -#define USB_SX353_PRODUCT_ID 0x0022 - -/* table of devices that work with this driver */ -static const struct usb_device_id gigaset_table[] = { - { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) }, - { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) }, - { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, - { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX353_PRODUCT_ID) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, gigaset_table); - -/*======================= local function prototypes ==========================*/ - -/* function called if a new device belonging to this driver is connected */ -static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id); - -/* Function will be called if the device is unplugged */ -static void gigaset_disconnect(struct usb_interface *interface); - -/* functions called before/after suspend */ -static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); -static int gigaset_resume(struct usb_interface *intf); - -/* functions called before/after device reset */ -static int gigaset_pre_reset(struct usb_interface *intf); -static int gigaset_post_reset(struct usb_interface *intf); - -static int atread_submit(struct cardstate *, int); -static void stopurbs(struct bas_bc_state *); -static int req_submit(struct bc_state *, int, int, int); -static int atwrite_submit(struct cardstate *, unsigned char *, int); -static int start_cbsend(struct cardstate *); - -/*============================================================================*/ - -struct bas_cardstate { - struct usb_device *udev; /* USB device pointer */ - struct cardstate *cs; - struct usb_interface *interface; /* interface for this device */ - unsigned char minor; /* starting minor number */ - - struct urb *urb_ctrl; /* control pipe default URB */ - struct usb_ctrlrequest dr_ctrl; - struct timer_list timer_ctrl; /* control request timeout */ - int retry_ctrl; - - struct timer_list timer_atrdy; /* AT command ready timeout */ - struct urb *urb_cmd_out; /* for sending AT commands */ - struct usb_ctrlrequest dr_cmd_out; - int retry_cmd_out; - - struct urb *urb_cmd_in; /* for receiving AT replies */ - struct usb_ctrlrequest dr_cmd_in; - struct timer_list timer_cmd_in; /* receive request timeout */ - unsigned char *rcvbuf; /* AT reply receive buffer */ - - struct urb *urb_int_in; /* URB for interrupt pipe */ - unsigned char *int_in_buf; - struct work_struct int_in_wq; /* for usb_clear_halt() */ - struct timer_list timer_int_in; /* int read retry delay */ - int retry_int_in; - - spinlock_t lock; /* locks all following */ - int basstate; /* bitmap (BS_*) */ - int pending; /* uncompleted base request */ - wait_queue_head_t waitqueue; - int rcvbuf_size; /* size of AT receive buffer */ - /* 0: no receive in progress */ - int retry_cmd_in; /* receive req retry count */ -}; - -/* status of direct USB connection to 307x base (bits in basstate) */ -#define BS_ATOPEN 0x001 /* AT channel open */ -#define BS_B1OPEN 0x002 /* B channel 1 open */ -#define BS_B2OPEN 0x004 /* B channel 2 open */ -#define BS_ATREADY 0x008 /* base ready for AT command */ -#define BS_INIT 0x010 /* base has signalled INIT_OK */ -#define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */ -#define BS_ATRDPEND 0x040 /* urb_cmd_in in use */ -#define BS_ATWRPEND 0x080 /* urb_cmd_out in use */ -#define BS_SUSPEND 0x100 /* USB port suspended */ -#define BS_RESETTING 0x200 /* waiting for HD_RESET_INTERRUPT_PIPE_ACK */ - - -static struct gigaset_driver *driver; - -/* usb specific object needed to register this driver with the usb subsystem */ -static struct usb_driver gigaset_usb_driver = { - .name = GIGASET_MODULENAME, - .probe = gigaset_probe, - .disconnect = gigaset_disconnect, - .id_table = gigaset_table, - .suspend = gigaset_suspend, - .resume = gigaset_resume, - .reset_resume = gigaset_post_reset, - .pre_reset = gigaset_pre_reset, - .post_reset = gigaset_post_reset, - .disable_hub_initiated_lpm = 1, -}; - -/* get message text for usb_submit_urb return code - */ -static char *get_usb_rcmsg(int rc) -{ - static char unkmsg[28]; - - switch (rc) { - case 0: - return "success"; - case -ENOMEM: - return "out of memory"; - case -ENODEV: - return "device not present"; - case -ENOENT: - return "endpoint not present"; - case -ENXIO: - return "URB type not supported"; - case -EINVAL: - return "invalid argument"; - case -EAGAIN: - return "start frame too early or too much scheduled"; - case -EFBIG: - return "too many isoc frames requested"; - case -EPIPE: - return "endpoint stalled"; - case -EMSGSIZE: - return "invalid packet size"; - case -ENOSPC: - return "would overcommit USB bandwidth"; - case -ESHUTDOWN: - return "device shut down"; - case -EPERM: - return "reject flag set"; - case -EHOSTUNREACH: - return "device suspended"; - default: - snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", rc); - return unkmsg; - } -} - -/* get message text for USB status code - */ -static char *get_usb_statmsg(int status) -{ - static char unkmsg[28]; - - switch (status) { - case 0: - return "success"; - case -ENOENT: - return "unlinked (sync)"; - case -EINPROGRESS: - return "URB still pending"; - case -EPROTO: - return "bitstuff error, timeout, or unknown USB error"; - case -EILSEQ: - return "CRC mismatch, timeout, or unknown USB error"; - case -ETIME: - return "USB response timeout"; - case -EPIPE: - return "endpoint stalled"; - case -ECOMM: - return "IN buffer overrun"; - case -ENOSR: - return "OUT buffer underrun"; - case -EOVERFLOW: - return "endpoint babble"; - case -EREMOTEIO: - return "short packet"; - case -ENODEV: - return "device removed"; - case -EXDEV: - return "partial isoc transfer"; - case -EINVAL: - return "ISO madness"; - case -ECONNRESET: - return "unlinked (async)"; - case -ESHUTDOWN: - return "device shut down"; - default: - snprintf(unkmsg, sizeof(unkmsg), "unknown status %d", status); - return unkmsg; - } -} - -/* usb_pipetype_str - * retrieve string representation of USB pipe type - */ -static inline char *usb_pipetype_str(int pipe) -{ - if (usb_pipeisoc(pipe)) - return "Isoc"; - if (usb_pipeint(pipe)) - return "Int"; - if (usb_pipecontrol(pipe)) - return "Ctrl"; - if (usb_pipebulk(pipe)) - return "Bulk"; - return "?"; -} - -/* dump_urb - * write content of URB to syslog for debugging - */ -static inline void dump_urb(enum debuglevel level, const char *tag, - struct urb *urb) -{ -#ifdef CONFIG_GIGASET_DEBUG - int i; - gig_dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb); - if (urb) { - gig_dbg(level, - " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " - "hcpriv=0x%08lx, transfer_flags=0x%x,", - (unsigned long) urb->dev, - usb_pipetype_str(urb->pipe), - usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out", - (unsigned long) urb->hcpriv, - urb->transfer_flags); - gig_dbg(level, - " transfer_buffer=0x%08lx[%d], actual_length=%d, " - "setup_packet=0x%08lx,", - (unsigned long) urb->transfer_buffer, - urb->transfer_buffer_length, urb->actual_length, - (unsigned long) urb->setup_packet); - gig_dbg(level, - " start_frame=%d, number_of_packets=%d, interval=%d, " - "error_count=%d,", - urb->start_frame, urb->number_of_packets, urb->interval, - urb->error_count); - gig_dbg(level, - " context=0x%08lx, complete=0x%08lx, " - "iso_frame_desc[]={", - (unsigned long) urb->context, - (unsigned long) urb->complete); - for (i = 0; i < urb->number_of_packets; i++) { - struct usb_iso_packet_descriptor *pifd - = &urb->iso_frame_desc[i]; - gig_dbg(level, - " {offset=%u, length=%u, actual_length=%u, " - "status=%u}", - pifd->offset, pifd->length, pifd->actual_length, - pifd->status); - } - } - gig_dbg(level, "}}"); -#endif -} - -/* read/set modem control bits etc. (m10x only) */ -static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) -{ - return -EINVAL; -} - -static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) -{ - return -EINVAL; -} - -static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) -{ - return -EINVAL; -} - -/* set/clear bits in base connection state, return previous state - */ -static inline int update_basstate(struct bas_cardstate *ucs, - int set, int clear) -{ - unsigned long flags; - int state; - - spin_lock_irqsave(&ucs->lock, flags); - state = ucs->basstate; - ucs->basstate = (state & ~clear) | set; - spin_unlock_irqrestore(&ucs->lock, flags); - return state; -} - -/* error_hangup - * hang up any existing connection because of an unrecoverable error - * This function may be called from any context and takes care of scheduling - * the necessary actions for execution outside of interrupt context. - * cs->lock must not be held. - * argument: - * B channel control structure - */ -static inline void error_hangup(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - - gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL); - gigaset_schedule_event(cs); -} - -/* error_reset - * reset Gigaset device because of an unrecoverable error - * This function may be called from any context, and takes care of - * scheduling the necessary actions for execution outside of interrupt context. - * cs->hw.bas->lock must not be held. - * argument: - * controller state structure - */ -static inline void error_reset(struct cardstate *cs) -{ - /* reset interrupt pipe to recover (ignore errors) */ - update_basstate(cs->hw.bas, BS_RESETTING, 0); - if (req_submit(cs->bcs, HD_RESET_INTERRUPT_PIPE, 0, BAS_TIMEOUT)) - /* submission failed, escalate to USB port reset */ - usb_queue_reset_device(cs->hw.bas->interface); -} - -/* check_pending - * check for completion of pending control request - * parameter: - * ucs hardware specific controller state structure - */ -static void check_pending(struct bas_cardstate *ucs) -{ - unsigned long flags; - - spin_lock_irqsave(&ucs->lock, flags); - switch (ucs->pending) { - case 0: - break; - case HD_OPEN_ATCHANNEL: - if (ucs->basstate & BS_ATOPEN) - ucs->pending = 0; - break; - case HD_OPEN_B1CHANNEL: - if (ucs->basstate & BS_B1OPEN) - ucs->pending = 0; - break; - case HD_OPEN_B2CHANNEL: - if (ucs->basstate & BS_B2OPEN) - ucs->pending = 0; - break; - case HD_CLOSE_ATCHANNEL: - if (!(ucs->basstate & BS_ATOPEN)) - ucs->pending = 0; - break; - case HD_CLOSE_B1CHANNEL: - if (!(ucs->basstate & BS_B1OPEN)) - ucs->pending = 0; - break; - case HD_CLOSE_B2CHANNEL: - if (!(ucs->basstate & BS_B2OPEN)) - ucs->pending = 0; - break; - case HD_DEVICE_INIT_ACK: /* no reply expected */ - ucs->pending = 0; - break; - case HD_RESET_INTERRUPT_PIPE: - if (!(ucs->basstate & BS_RESETTING)) - ucs->pending = 0; - break; - /* - * HD_READ_ATMESSAGE and HD_WRITE_ATMESSAGE are handled separately - * and should never end up here - */ - default: - dev_warn(&ucs->interface->dev, - "unknown pending request 0x%02x cleared\n", - ucs->pending); - ucs->pending = 0; - } - - if (!ucs->pending) - del_timer(&ucs->timer_ctrl); - - spin_unlock_irqrestore(&ucs->lock, flags); -} - -/* cmd_in_timeout - * timeout routine for command input request - * argument: - * controller state structure - */ -static void cmd_in_timeout(struct timer_list *t) -{ - struct bas_cardstate *ucs = from_timer(ucs, t, timer_cmd_in); - struct cardstate *cs = ucs->cs; - int rc; - - if (!ucs->rcvbuf_size) { - gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); - return; - } - - if (ucs->retry_cmd_in++ >= BAS_RETRY) { - dev_err(cs->dev, - "control read: timeout, giving up after %d tries\n", - ucs->retry_cmd_in); - kfree(ucs->rcvbuf); - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; - error_reset(cs); - return; - } - - gig_dbg(DEBUG_USBREQ, "%s: timeout, retry %d", - __func__, ucs->retry_cmd_in); - rc = atread_submit(cs, BAS_TIMEOUT); - if (rc < 0) { - kfree(ucs->rcvbuf); - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; - if (rc != -ENODEV) - error_reset(cs); - } -} - -/* read_ctrl_callback - * USB completion handler for control pipe input - * called by the USB subsystem in interrupt context - * parameter: - * urb USB request block - * urb->context = inbuf structure for controller state - */ -static void read_ctrl_callback(struct urb *urb) -{ - struct inbuf_t *inbuf = urb->context; - struct cardstate *cs = inbuf->cs; - struct bas_cardstate *ucs = cs->hw.bas; - int status = urb->status; - unsigned numbytes; - int rc; - - update_basstate(ucs, 0, BS_ATRDPEND); - wake_up(&ucs->waitqueue); - del_timer(&ucs->timer_cmd_in); - - switch (status) { - case 0: /* normal completion */ - numbytes = urb->actual_length; - if (unlikely(numbytes != ucs->rcvbuf_size)) { - dev_warn(cs->dev, - "control read: received %d chars, expected %d\n", - numbytes, ucs->rcvbuf_size); - if (numbytes > ucs->rcvbuf_size) - numbytes = ucs->rcvbuf_size; - } - - /* copy received bytes to inbuf, notify event layer */ - if (gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes)) { - gig_dbg(DEBUG_INTR, "%s-->BH", __func__); - gigaset_schedule_event(cs); - } - break; - - case -ENOENT: /* cancelled */ - case -ECONNRESET: /* cancelled (async) */ - case -EINPROGRESS: /* pending */ - case -ENODEV: /* device removed */ - case -ESHUTDOWN: /* device shut down */ - /* no further action necessary */ - gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(status)); - break; - - default: /* other errors: retry */ - if (ucs->retry_cmd_in++ < BAS_RETRY) { - gig_dbg(DEBUG_USBREQ, "%s: %s, retry %d", __func__, - get_usb_statmsg(status), ucs->retry_cmd_in); - rc = atread_submit(cs, BAS_TIMEOUT); - if (rc >= 0) - /* successfully resubmitted, skip freeing */ - return; - if (rc == -ENODEV) - /* disconnect, no further action necessary */ - break; - } - dev_err(cs->dev, "control read: %s, giving up after %d tries\n", - get_usb_statmsg(status), ucs->retry_cmd_in); - error_reset(cs); - } - - /* read finished, free buffer */ - kfree(ucs->rcvbuf); - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; -} - -/* atread_submit - * submit an HD_READ_ATMESSAGE command URB and optionally start a timeout - * parameters: - * cs controller state structure - * timeout timeout in 1/10 sec., 0: none - * return value: - * 0 on success - * -EBUSY if another request is pending - * any URB submission error code - */ -static int atread_submit(struct cardstate *cs, int timeout) -{ - struct bas_cardstate *ucs = cs->hw.bas; - int basstate; - int ret; - - gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", - ucs->rcvbuf_size); - - basstate = update_basstate(ucs, BS_ATRDPEND, 0); - if (basstate & BS_ATRDPEND) { - dev_err(cs->dev, - "could not submit HD_READ_ATMESSAGE: URB busy\n"); - return -EBUSY; - } - - if (basstate & BS_SUSPEND) { - dev_notice(cs->dev, - "HD_READ_ATMESSAGE not submitted, " - "suspend in progress\n"); - update_basstate(ucs, 0, BS_ATRDPEND); - /* treat like disconnect */ - return -ENODEV; - } - - ucs->dr_cmd_in.bRequestType = IN_VENDOR_REQ; - ucs->dr_cmd_in.bRequest = HD_READ_ATMESSAGE; - ucs->dr_cmd_in.wValue = 0; - ucs->dr_cmd_in.wIndex = 0; - ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size); - usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev, - usb_rcvctrlpipe(ucs->udev, 0), - (unsigned char *) &ucs->dr_cmd_in, - ucs->rcvbuf, ucs->rcvbuf_size, - read_ctrl_callback, cs->inbuf); - - ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC); - if (ret != 0) { - update_basstate(ucs, 0, BS_ATRDPEND); - dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", - get_usb_rcmsg(ret)); - return ret; - } - - if (timeout > 0) { - gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); - mod_timer(&ucs->timer_cmd_in, jiffies + timeout * HZ / 10); - } - return 0; -} - -/* int_in_work - * workqueue routine to clear halt on interrupt in endpoint - */ - -static void int_in_work(struct work_struct *work) -{ - struct bas_cardstate *ucs = - container_of(work, struct bas_cardstate, int_in_wq); - struct urb *urb = ucs->urb_int_in; - struct cardstate *cs = urb->context; - int rc; - - /* clear halt condition */ - rc = usb_clear_halt(ucs->udev, urb->pipe); - gig_dbg(DEBUG_USBREQ, "clear_halt: %s", get_usb_rcmsg(rc)); - if (rc == 0) - /* success, resubmit interrupt read URB */ - rc = usb_submit_urb(urb, GFP_ATOMIC); - - switch (rc) { - case 0: /* success */ - case -ENODEV: /* device gone */ - case -EINVAL: /* URB already resubmitted, or terminal badness */ - break; - default: /* failure: try to recover by resetting the device */ - dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc)); - rc = usb_lock_device_for_reset(ucs->udev, ucs->interface); - if (rc == 0) { - rc = usb_reset_device(ucs->udev); - usb_unlock_device(ucs->udev); - } - } - ucs->retry_int_in = 0; -} - -/* int_in_resubmit - * timer routine for interrupt read delayed resubmit - * argument: - * controller state structure - */ -static void int_in_resubmit(struct timer_list *t) -{ - struct bas_cardstate *ucs = from_timer(ucs, t, timer_int_in); - struct cardstate *cs = ucs->cs; - int rc; - - if (ucs->retry_int_in++ >= BAS_RETRY) { - dev_err(cs->dev, "interrupt read: giving up after %d tries\n", - ucs->retry_int_in); - usb_queue_reset_device(ucs->interface); - return; - } - - gig_dbg(DEBUG_USBREQ, "%s: retry %d", __func__, ucs->retry_int_in); - rc = usb_submit_urb(ucs->urb_int_in, GFP_ATOMIC); - if (rc != 0 && rc != -ENODEV) { - dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", - get_usb_rcmsg(rc)); - usb_queue_reset_device(ucs->interface); - } -} - -/* read_int_callback - * USB completion handler for interrupt pipe input - * called by the USB subsystem in interrupt context - * parameter: - * urb USB request block - * urb->context = controller state structure - */ -static void read_int_callback(struct urb *urb) -{ - struct cardstate *cs = urb->context; - struct bas_cardstate *ucs = cs->hw.bas; - struct bc_state *bcs; - int status = urb->status; - unsigned long flags; - int rc; - unsigned l; - int channel; - - switch (status) { - case 0: /* success */ - ucs->retry_int_in = 0; - break; - case -EPIPE: /* endpoint stalled */ - schedule_work(&ucs->int_in_wq); - /* fall through */ - case -ENOENT: /* cancelled */ - case -ECONNRESET: /* cancelled (async) */ - case -EINPROGRESS: /* pending */ - case -ENODEV: /* device removed */ - case -ESHUTDOWN: /* device shut down */ - /* no further action necessary */ - gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(status)); - return; - case -EPROTO: /* protocol error or unplug */ - case -EILSEQ: - case -ETIME: - /* resubmit after delay */ - gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(status)); - mod_timer(&ucs->timer_int_in, jiffies + HZ / 10); - return; - default: /* other errors: just resubmit */ - dev_warn(cs->dev, "interrupt read: %s\n", - get_usb_statmsg(status)); - goto resubmit; - } - - /* drop incomplete packets even if the missing bytes wouldn't matter */ - if (unlikely(urb->actual_length < IP_MSGSIZE)) { - dev_warn(cs->dev, "incomplete interrupt packet (%d bytes)\n", - urb->actual_length); - goto resubmit; - } - - l = (unsigned) ucs->int_in_buf[1] + - (((unsigned) ucs->int_in_buf[2]) << 8); - - gig_dbg(DEBUG_USBREQ, "<-------%d: 0x%02x (%u [0x%02x 0x%02x])", - urb->actual_length, (int)ucs->int_in_buf[0], l, - (int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]); - - channel = 0; - - switch (ucs->int_in_buf[0]) { - case HD_DEVICE_INIT_OK: - update_basstate(ucs, BS_INIT, 0); - break; - - case HD_READY_SEND_ATDATA: - del_timer(&ucs->timer_atrdy); - update_basstate(ucs, BS_ATREADY, BS_ATTIMER); - start_cbsend(cs); - break; - - case HD_OPEN_B2CHANNEL_ACK: - ++channel; - /* fall through */ - case HD_OPEN_B1CHANNEL_ACK: - bcs = cs->bcs + channel; - update_basstate(ucs, BS_B1OPEN << channel, 0); - gigaset_bchannel_up(bcs); - break; - - case HD_OPEN_ATCHANNEL_ACK: - update_basstate(ucs, BS_ATOPEN, 0); - start_cbsend(cs); - break; - - case HD_CLOSE_B2CHANNEL_ACK: - ++channel; - /* fall through */ - case HD_CLOSE_B1CHANNEL_ACK: - bcs = cs->bcs + channel; - update_basstate(ucs, 0, BS_B1OPEN << channel); - stopurbs(bcs->hw.bas); - gigaset_bchannel_down(bcs); - break; - - case HD_CLOSE_ATCHANNEL_ACK: - update_basstate(ucs, 0, BS_ATOPEN); - break; - - case HD_B2_FLOW_CONTROL: - ++channel; - /* fall through */ - case HD_B1_FLOW_CONTROL: - bcs = cs->bcs + channel; - atomic_add((l - BAS_NORMFRAME) * BAS_CORRFRAMES, - &bcs->hw.bas->corrbytes); - gig_dbg(DEBUG_ISO, - "Flow control (channel %d, sub %d): 0x%02x => %d", - channel, bcs->hw.bas->numsub, l, - atomic_read(&bcs->hw.bas->corrbytes)); - break; - - case HD_RECEIVEATDATA_ACK: /* AT response ready to be received */ - if (!l) { - dev_warn(cs->dev, - "HD_RECEIVEATDATA_ACK with length 0 ignored\n"); - break; - } - spin_lock_irqsave(&cs->lock, flags); - if (ucs->basstate & BS_ATRDPEND) { - spin_unlock_irqrestore(&cs->lock, flags); - dev_warn(cs->dev, - "HD_RECEIVEATDATA_ACK(%d) during HD_READ_ATMESSAGE(%d) ignored\n", - l, ucs->rcvbuf_size); - break; - } - if (ucs->rcvbuf_size) { - /* throw away previous buffer - we have no queue */ - dev_err(cs->dev, - "receive AT data overrun, %d bytes lost\n", - ucs->rcvbuf_size); - kfree(ucs->rcvbuf); - ucs->rcvbuf_size = 0; - } - ucs->rcvbuf = kmalloc(l, GFP_ATOMIC); - if (ucs->rcvbuf == NULL) { - spin_unlock_irqrestore(&cs->lock, flags); - dev_err(cs->dev, "out of memory receiving AT data\n"); - break; - } - ucs->rcvbuf_size = l; - ucs->retry_cmd_in = 0; - rc = atread_submit(cs, BAS_TIMEOUT); - if (rc < 0) { - kfree(ucs->rcvbuf); - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; - } - spin_unlock_irqrestore(&cs->lock, flags); - if (rc < 0 && rc != -ENODEV) - error_reset(cs); - break; - - case HD_RESET_INTERRUPT_PIPE_ACK: - update_basstate(ucs, 0, BS_RESETTING); - dev_notice(cs->dev, "interrupt pipe reset\n"); - break; - - case HD_SUSPEND_END: - gig_dbg(DEBUG_USBREQ, "HD_SUSPEND_END"); - break; - - default: - dev_warn(cs->dev, - "unknown Gigaset signal 0x%02x (%u) ignored\n", - (int) ucs->int_in_buf[0], l); - } - - check_pending(ucs); - wake_up(&ucs->waitqueue); - -resubmit: - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(rc != 0 && rc != -ENODEV)) { - dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", - get_usb_rcmsg(rc)); - error_reset(cs); - } -} - -/* read_iso_callback - * USB completion handler for B channel isochronous input - * called by the USB subsystem in interrupt context - * parameter: - * urb USB request block of completed request - * urb->context = bc_state structure - */ -static void read_iso_callback(struct urb *urb) -{ - struct bc_state *bcs; - struct bas_bc_state *ubc; - int status = urb->status; - unsigned long flags; - int i, rc; - - /* status codes not worth bothering the tasklet with */ - if (unlikely(status == -ENOENT || - status == -ECONNRESET || - status == -EINPROGRESS || - status == -ENODEV || - status == -ESHUTDOWN)) { - gig_dbg(DEBUG_ISO, "%s: %s", - __func__, get_usb_statmsg(status)); - return; - } - - bcs = urb->context; - ubc = bcs->hw.bas; - - spin_lock_irqsave(&ubc->isoinlock, flags); - if (likely(ubc->isoindone == NULL)) { - /* pass URB to tasklet */ - ubc->isoindone = urb; - ubc->isoinstatus = status; - tasklet_hi_schedule(&ubc->rcvd_tasklet); - } else { - /* tasklet still busy, drop data and resubmit URB */ - gig_dbg(DEBUG_ISO, "%s: overrun", __func__); - ubc->loststatus = status; - for (i = 0; i < BAS_NUMFRAMES; i++) { - ubc->isoinlost += urb->iso_frame_desc[i].actual_length; - if (unlikely(urb->iso_frame_desc[i].status != 0 && - urb->iso_frame_desc[i].status != -EINPROGRESS)) - ubc->loststatus = urb->iso_frame_desc[i].status; - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - if (likely(ubc->running)) { - /* urb->dev is clobbered by USB subsystem */ - urb->dev = bcs->cs->hw.bas->udev; - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = BAS_NUMFRAMES; - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(rc != 0 && rc != -ENODEV)) { - dev_err(bcs->cs->dev, - "could not resubmit isoc read URB: %s\n", - get_usb_rcmsg(rc)); - dump_urb(DEBUG_ISO, "isoc read", urb); - error_hangup(bcs); - } - } - } - spin_unlock_irqrestore(&ubc->isoinlock, flags); -} - -/* write_iso_callback - * USB completion handler for B channel isochronous output - * called by the USB subsystem in interrupt context - * parameter: - * urb USB request block of completed request - * urb->context = isow_urbctx_t structure - */ -static void write_iso_callback(struct urb *urb) -{ - struct isow_urbctx_t *ucx; - struct bas_bc_state *ubc; - int status = urb->status; - unsigned long flags; - - /* status codes not worth bothering the tasklet with */ - if (unlikely(status == -ENOENT || - status == -ECONNRESET || - status == -EINPROGRESS || - status == -ENODEV || - status == -ESHUTDOWN)) { - gig_dbg(DEBUG_ISO, "%s: %s", - __func__, get_usb_statmsg(status)); - return; - } - - /* pass URB context to tasklet */ - ucx = urb->context; - ubc = ucx->bcs->hw.bas; - ucx->status = status; - - spin_lock_irqsave(&ubc->isooutlock, flags); - ubc->isooutovfl = ubc->isooutdone; - ubc->isooutdone = ucx; - spin_unlock_irqrestore(&ubc->isooutlock, flags); - tasklet_hi_schedule(&ubc->sent_tasklet); -} - -/* starturbs - * prepare and submit USB request blocks for isochronous input and output - * argument: - * B channel control structure - * return value: - * 0 on success - * < 0 on error (no URBs submitted) - */ -static int starturbs(struct bc_state *bcs) -{ - struct usb_device *udev = bcs->cs->hw.bas->udev; - struct bas_bc_state *ubc = bcs->hw.bas; - struct urb *urb; - int j, k; - int rc; - - /* initialize L2 reception */ - if (bcs->proto2 == L2_HDLC) - bcs->inputstate |= INS_flag_hunt; - - /* submit all isochronous input URBs */ - ubc->running = 1; - for (k = 0; k < BAS_INURBS; k++) { - urb = ubc->isoinurbs[k]; - if (!urb) { - rc = -EFAULT; - goto error; - } - usb_fill_int_urb(urb, udev, - usb_rcvisocpipe(udev, 3 + 2 * bcs->channel), - ubc->isoinbuf + k * BAS_INBUFSIZE, - BAS_INBUFSIZE, read_iso_callback, bcs, - BAS_FRAMETIME); - - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = BAS_NUMFRAMES; - for (j = 0; j < BAS_NUMFRAMES; j++) { - urb->iso_frame_desc[j].offset = j * BAS_MAXFRAME; - urb->iso_frame_desc[j].length = BAS_MAXFRAME; - urb->iso_frame_desc[j].status = 0; - urb->iso_frame_desc[j].actual_length = 0; - } - - dump_urb(DEBUG_ISO, "Initial isoc read", urb); - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc != 0) - goto error; - } - - /* initialize L2 transmission */ - gigaset_isowbuf_init(ubc->isooutbuf, PPP_FLAG); - - /* set up isochronous output URBs for flag idling */ - for (k = 0; k < BAS_OUTURBS; ++k) { - urb = ubc->isoouturbs[k].urb; - if (!urb) { - rc = -EFAULT; - goto error; - } - usb_fill_int_urb(urb, udev, - usb_sndisocpipe(udev, 4 + 2 * bcs->channel), - ubc->isooutbuf->data, - sizeof(ubc->isooutbuf->data), - write_iso_callback, &ubc->isoouturbs[k], - BAS_FRAMETIME); - - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = BAS_NUMFRAMES; - for (j = 0; j < BAS_NUMFRAMES; ++j) { - urb->iso_frame_desc[j].offset = BAS_OUTBUFSIZE; - urb->iso_frame_desc[j].length = BAS_NORMFRAME; - urb->iso_frame_desc[j].status = 0; - urb->iso_frame_desc[j].actual_length = 0; - } - ubc->isoouturbs[k].limit = -1; - } - - /* keep one URB free, submit the others */ - for (k = 0; k < BAS_OUTURBS - 1; ++k) { - dump_urb(DEBUG_ISO, "Initial isoc write", urb); - rc = usb_submit_urb(ubc->isoouturbs[k].urb, GFP_ATOMIC); - if (rc != 0) - goto error; - } - dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); - ubc->isooutfree = &ubc->isoouturbs[BAS_OUTURBS - 1]; - ubc->isooutdone = ubc->isooutovfl = NULL; - return 0; -error: - stopurbs(ubc); - return rc; -} - -/* stopurbs - * cancel the USB request blocks for isochronous input and output - * errors are silently ignored - * argument: - * B channel control structure - */ -static void stopurbs(struct bas_bc_state *ubc) -{ - int k, rc; - - ubc->running = 0; - - for (k = 0; k < BAS_INURBS; ++k) { - rc = usb_unlink_urb(ubc->isoinurbs[k]); - gig_dbg(DEBUG_ISO, - "%s: isoc input URB %d unlinked, result = %s", - __func__, k, get_usb_rcmsg(rc)); - } - - for (k = 0; k < BAS_OUTURBS; ++k) { - rc = usb_unlink_urb(ubc->isoouturbs[k].urb); - gig_dbg(DEBUG_ISO, - "%s: isoc output URB %d unlinked, result = %s", - __func__, k, get_usb_rcmsg(rc)); - } -} - -/* Isochronous Write - Bottom Half */ -/* =============================== */ - -/* submit_iso_write_urb - * fill and submit the next isochronous write URB - * parameters: - * ucx context structure containing URB - * return value: - * number of frames submitted in URB - * 0 if URB not submitted because no data available (isooutbuf busy) - * error code < 0 on error - */ -static int submit_iso_write_urb(struct isow_urbctx_t *ucx) -{ - struct urb *urb = ucx->urb; - struct bas_bc_state *ubc = ucx->bcs->hw.bas; - struct usb_iso_packet_descriptor *ifd; - int corrbytes, nframe, rc; - - /* urb->dev is clobbered by USB subsystem */ - urb->dev = ucx->bcs->cs->hw.bas->udev; - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = ubc->isooutbuf->data; - urb->transfer_buffer_length = sizeof(ubc->isooutbuf->data); - - for (nframe = 0; nframe < BAS_NUMFRAMES; nframe++) { - ifd = &urb->iso_frame_desc[nframe]; - - /* compute frame length according to flow control */ - ifd->length = BAS_NORMFRAME; - corrbytes = atomic_read(&ubc->corrbytes); - if (corrbytes != 0) { - gig_dbg(DEBUG_ISO, "%s: corrbytes=%d", - __func__, corrbytes); - if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME) - corrbytes = BAS_HIGHFRAME - BAS_NORMFRAME; - else if (corrbytes < BAS_LOWFRAME - BAS_NORMFRAME) - corrbytes = BAS_LOWFRAME - BAS_NORMFRAME; - ifd->length += corrbytes; - atomic_add(-corrbytes, &ubc->corrbytes); - } - - /* retrieve block of data to send */ - rc = gigaset_isowbuf_getbytes(ubc->isooutbuf, ifd->length); - if (rc < 0) { - if (rc == -EBUSY) { - gig_dbg(DEBUG_ISO, - "%s: buffer busy at frame %d", - __func__, nframe); - /* tasklet will be restarted from - gigaset_isoc_send_skb() */ - } else { - dev_err(ucx->bcs->cs->dev, - "%s: buffer error %d at frame %d\n", - __func__, rc, nframe); - return rc; - } - break; - } - ifd->offset = rc; - ucx->limit = ubc->isooutbuf->nextread; - ifd->status = 0; - ifd->actual_length = 0; - } - if (unlikely(nframe == 0)) - return 0; /* no data to send */ - urb->number_of_packets = nframe; - - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(rc)) { - if (rc == -ENODEV) - /* device removed - give up silently */ - gig_dbg(DEBUG_ISO, "%s: disconnected", __func__); - else - dev_err(ucx->bcs->cs->dev, - "could not submit isoc write URB: %s\n", - get_usb_rcmsg(rc)); - return rc; - } - ++ubc->numsub; - return nframe; -} - -/* write_iso_tasklet - * tasklet scheduled when an isochronous output URB from the Gigaset device - * has completed - * parameter: - * data B channel state structure - */ -static void write_iso_tasklet(unsigned long data) -{ - struct bc_state *bcs = (struct bc_state *) data; - struct bas_bc_state *ubc = bcs->hw.bas; - struct cardstate *cs = bcs->cs; - struct isow_urbctx_t *done, *next, *ovfl; - struct urb *urb; - int status; - struct usb_iso_packet_descriptor *ifd; - unsigned long flags; - int i; - struct sk_buff *skb; - int len; - int rc; - - /* loop while completed URBs arrive in time */ - for (;;) { - if (unlikely(!(ubc->running))) { - gig_dbg(DEBUG_ISO, "%s: not running", __func__); - return; - } - - /* retrieve completed URBs */ - spin_lock_irqsave(&ubc->isooutlock, flags); - done = ubc->isooutdone; - ubc->isooutdone = NULL; - ovfl = ubc->isooutovfl; - ubc->isooutovfl = NULL; - spin_unlock_irqrestore(&ubc->isooutlock, flags); - if (ovfl) { - dev_err(cs->dev, "isoc write underrun\n"); - error_hangup(bcs); - break; - } - if (!done) - break; - - /* submit free URB if available */ - spin_lock_irqsave(&ubc->isooutlock, flags); - next = ubc->isooutfree; - ubc->isooutfree = NULL; - spin_unlock_irqrestore(&ubc->isooutlock, flags); - if (next) { - rc = submit_iso_write_urb(next); - if (unlikely(rc <= 0 && rc != -ENODEV)) { - /* could not submit URB, put it back */ - spin_lock_irqsave(&ubc->isooutlock, flags); - if (ubc->isooutfree == NULL) { - ubc->isooutfree = next; - next = NULL; - } - spin_unlock_irqrestore(&ubc->isooutlock, flags); - if (next) { - /* couldn't put it back */ - dev_err(cs->dev, - "losing isoc write URB\n"); - error_hangup(bcs); - } - } - } - - /* process completed URB */ - urb = done->urb; - status = done->status; - switch (status) { - case -EXDEV: /* partial completion */ - gig_dbg(DEBUG_ISO, "%s: URB partially completed", - __func__); - /* fall through - what's the difference anyway? */ - case 0: /* normal completion */ - /* inspect individual frames - * assumptions (for lack of documentation): - * - actual_length bytes of first frame in error are - * successfully sent - * - all following frames are not sent at all - */ - for (i = 0; i < BAS_NUMFRAMES; i++) { - ifd = &urb->iso_frame_desc[i]; - if (ifd->status || - ifd->actual_length != ifd->length) { - dev_warn(cs->dev, - "isoc write: frame %d[%d/%d]: %s\n", - i, ifd->actual_length, - ifd->length, - get_usb_statmsg(ifd->status)); - break; - } - } - break; - case -EPIPE: /* stall - probably underrun */ - dev_err(cs->dev, "isoc write: stalled\n"); - error_hangup(bcs); - break; - default: /* other errors */ - dev_warn(cs->dev, "isoc write: %s\n", - get_usb_statmsg(status)); - } - - /* mark the write buffer area covered by this URB as free */ - if (done->limit >= 0) - ubc->isooutbuf->read = done->limit; - - /* mark URB as free */ - spin_lock_irqsave(&ubc->isooutlock, flags); - next = ubc->isooutfree; - ubc->isooutfree = done; - spin_unlock_irqrestore(&ubc->isooutlock, flags); - if (next) { - /* only one URB still active - resubmit one */ - rc = submit_iso_write_urb(next); - if (unlikely(rc <= 0 && rc != -ENODEV)) { - /* couldn't submit */ - error_hangup(bcs); - } - } - } - - /* process queued SKBs */ - while ((skb = skb_dequeue(&bcs->squeue))) { - /* copy to output buffer, doing L2 encapsulation */ - len = skb->len; - if (gigaset_isoc_buildframe(bcs, skb->data, len) == -EAGAIN) { - /* insufficient buffer space, push back onto queue */ - skb_queue_head(&bcs->squeue, skb); - gig_dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d", - __func__, skb_queue_len(&bcs->squeue)); - break; - } - skb_pull(skb, len); - gigaset_skb_sent(bcs, skb); - dev_kfree_skb_any(skb); - } -} - -/* Isochronous Read - Bottom Half */ -/* ============================== */ - -/* read_iso_tasklet - * tasklet scheduled when an isochronous input URB from the Gigaset device - * has completed - * parameter: - * data B channel state structure - */ -static void read_iso_tasklet(unsigned long data) -{ - struct bc_state *bcs = (struct bc_state *) data; - struct bas_bc_state *ubc = bcs->hw.bas; - struct cardstate *cs = bcs->cs; - struct urb *urb; - int status; - struct usb_iso_packet_descriptor *ifd; - char *rcvbuf; - unsigned long flags; - int totleft, numbytes, offset, frame, rc; - - /* loop while more completed URBs arrive in the meantime */ - for (;;) { - /* retrieve URB */ - spin_lock_irqsave(&ubc->isoinlock, flags); - urb = ubc->isoindone; - if (!urb) { - spin_unlock_irqrestore(&ubc->isoinlock, flags); - return; - } - status = ubc->isoinstatus; - ubc->isoindone = NULL; - if (unlikely(ubc->loststatus != -EINPROGRESS)) { - dev_warn(cs->dev, - "isoc read overrun, URB dropped (status: %s, %d bytes)\n", - get_usb_statmsg(ubc->loststatus), - ubc->isoinlost); - ubc->loststatus = -EINPROGRESS; - } - spin_unlock_irqrestore(&ubc->isoinlock, flags); - - if (unlikely(!(ubc->running))) { - gig_dbg(DEBUG_ISO, - "%s: channel not running, " - "dropped URB with status: %s", - __func__, get_usb_statmsg(status)); - return; - } - - switch (status) { - case 0: /* normal completion */ - break; - case -EXDEV: /* inspect individual frames - (we do that anyway) */ - gig_dbg(DEBUG_ISO, "%s: URB partially completed", - __func__); - break; - case -ENOENT: - case -ECONNRESET: - case -EINPROGRESS: - gig_dbg(DEBUG_ISO, "%s: %s", - __func__, get_usb_statmsg(status)); - continue; /* -> skip */ - case -EPIPE: - dev_err(cs->dev, "isoc read: stalled\n"); - error_hangup(bcs); - continue; /* -> skip */ - default: /* other error */ - dev_warn(cs->dev, "isoc read: %s\n", - get_usb_statmsg(status)); - goto error; - } - - rcvbuf = urb->transfer_buffer; - totleft = urb->actual_length; - for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) { - ifd = &urb->iso_frame_desc[frame]; - numbytes = ifd->actual_length; - switch (ifd->status) { - case 0: /* success */ - break; - case -EPROTO: /* protocol error or unplug */ - case -EILSEQ: - case -ETIME: - /* probably just disconnected, ignore */ - gig_dbg(DEBUG_ISO, - "isoc read: frame %d[%d]: %s\n", - frame, numbytes, - get_usb_statmsg(ifd->status)); - break; - default: /* other error */ - /* report, assume transferred bytes are ok */ - dev_warn(cs->dev, - "isoc read: frame %d[%d]: %s\n", - frame, numbytes, - get_usb_statmsg(ifd->status)); - } - if (unlikely(numbytes > BAS_MAXFRAME)) - dev_warn(cs->dev, - "isoc read: frame %d[%d]: %s\n", - frame, numbytes, - "exceeds max frame size"); - if (unlikely(numbytes > totleft)) { - dev_warn(cs->dev, - "isoc read: frame %d[%d]: %s\n", - frame, numbytes, - "exceeds total transfer length"); - numbytes = totleft; - } - offset = ifd->offset; - if (unlikely(offset + numbytes > BAS_INBUFSIZE)) { - dev_warn(cs->dev, - "isoc read: frame %d[%d]: %s\n", - frame, numbytes, - "exceeds end of buffer"); - numbytes = BAS_INBUFSIZE - offset; - } - gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs); - totleft -= numbytes; - } - if (unlikely(totleft > 0)) - dev_warn(cs->dev, "isoc read: %d data bytes missing\n", - totleft); - -error: - /* URB processed, resubmit */ - for (frame = 0; frame < BAS_NUMFRAMES; frame++) { - urb->iso_frame_desc[frame].status = 0; - urb->iso_frame_desc[frame].actual_length = 0; - } - /* urb->dev is clobbered by USB subsystem */ - urb->dev = bcs->cs->hw.bas->udev; - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = BAS_NUMFRAMES; - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(rc != 0 && rc != -ENODEV)) { - dev_err(cs->dev, - "could not resubmit isoc read URB: %s\n", - get_usb_rcmsg(rc)); - dump_urb(DEBUG_ISO, "resubmit isoc read", urb); - error_hangup(bcs); - } - } -} - -/* Channel Operations */ -/* ================== */ - -/* req_timeout - * timeout routine for control output request - * argument: - * controller state structure - */ -static void req_timeout(struct timer_list *t) -{ - struct bas_cardstate *ucs = from_timer(ucs, t, timer_ctrl); - struct cardstate *cs = ucs->cs; - int pending; - unsigned long flags; - - check_pending(ucs); - - spin_lock_irqsave(&ucs->lock, flags); - pending = ucs->pending; - ucs->pending = 0; - spin_unlock_irqrestore(&ucs->lock, flags); - - switch (pending) { - case 0: /* no pending request */ - gig_dbg(DEBUG_USBREQ, "%s: no request pending", __func__); - break; - - case HD_OPEN_ATCHANNEL: - dev_err(cs->dev, "timeout opening AT channel\n"); - error_reset(cs); - break; - - case HD_OPEN_B1CHANNEL: - dev_err(cs->dev, "timeout opening channel 1\n"); - error_hangup(&cs->bcs[0]); - break; - - case HD_OPEN_B2CHANNEL: - dev_err(cs->dev, "timeout opening channel 2\n"); - error_hangup(&cs->bcs[1]); - break; - - case HD_CLOSE_ATCHANNEL: - dev_err(cs->dev, "timeout closing AT channel\n"); - error_reset(cs); - break; - - case HD_CLOSE_B1CHANNEL: - dev_err(cs->dev, "timeout closing channel 1\n"); - error_reset(cs); - break; - - case HD_CLOSE_B2CHANNEL: - dev_err(cs->dev, "timeout closing channel 2\n"); - error_reset(cs); - break; - - case HD_RESET_INTERRUPT_PIPE: - /* error recovery escalation */ - dev_err(cs->dev, - "reset interrupt pipe timeout, attempting USB reset\n"); - usb_queue_reset_device(ucs->interface); - break; - - default: - dev_warn(cs->dev, "request 0x%02x timed out, clearing\n", - pending); - } - - wake_up(&ucs->waitqueue); -} - -/* write_ctrl_callback - * USB completion handler for control pipe output - * called by the USB subsystem in interrupt context - * parameter: - * urb USB request block of completed request - * urb->context = hardware specific controller state structure - */ -static void write_ctrl_callback(struct urb *urb) -{ - struct bas_cardstate *ucs = urb->context; - int status = urb->status; - int rc; - unsigned long flags; - - /* check status */ - switch (status) { - case 0: /* normal completion */ - spin_lock_irqsave(&ucs->lock, flags); - switch (ucs->pending) { - case HD_DEVICE_INIT_ACK: /* no reply expected */ - del_timer(&ucs->timer_ctrl); - ucs->pending = 0; - break; - } - spin_unlock_irqrestore(&ucs->lock, flags); - return; - - case -ENOENT: /* cancelled */ - case -ECONNRESET: /* cancelled (async) */ - case -EINPROGRESS: /* pending */ - case -ENODEV: /* device removed */ - case -ESHUTDOWN: /* device shut down */ - /* ignore silently */ - gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(status)); - break; - - default: /* any failure */ - /* don't retry if suspend requested */ - if (++ucs->retry_ctrl > BAS_RETRY || - (ucs->basstate & BS_SUSPEND)) { - dev_err(&ucs->interface->dev, - "control request 0x%02x failed: %s\n", - ucs->dr_ctrl.bRequest, - get_usb_statmsg(status)); - break; /* give up */ - } - dev_notice(&ucs->interface->dev, - "control request 0x%02x: %s, retry %d\n", - ucs->dr_ctrl.bRequest, get_usb_statmsg(status), - ucs->retry_ctrl); - /* urb->dev is clobbered by USB subsystem */ - urb->dev = ucs->udev; - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(rc)) { - dev_err(&ucs->interface->dev, - "could not resubmit request 0x%02x: %s\n", - ucs->dr_ctrl.bRequest, get_usb_rcmsg(rc)); - break; - } - /* resubmitted */ - return; - } - - /* failed, clear pending request */ - spin_lock_irqsave(&ucs->lock, flags); - del_timer(&ucs->timer_ctrl); - ucs->pending = 0; - spin_unlock_irqrestore(&ucs->lock, flags); - wake_up(&ucs->waitqueue); -} - -/* req_submit - * submit a control output request without message buffer to the Gigaset base - * and optionally start a timeout - * parameters: - * bcs B channel control structure - * req control request code (HD_*) - * val control request parameter value (set to 0 if unused) - * timeout timeout in seconds (0: no timeout) - * return value: - * 0 on success - * -EBUSY if another request is pending - * any URB submission error code - */ -static int req_submit(struct bc_state *bcs, int req, int val, int timeout) -{ - struct bas_cardstate *ucs = bcs->cs->hw.bas; - int ret; - unsigned long flags; - - gig_dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val); - - spin_lock_irqsave(&ucs->lock, flags); - if (ucs->pending) { - spin_unlock_irqrestore(&ucs->lock, flags); - dev_err(bcs->cs->dev, - "submission of request 0x%02x failed: " - "request 0x%02x still pending\n", - req, ucs->pending); - return -EBUSY; - } - - ucs->dr_ctrl.bRequestType = OUT_VENDOR_REQ; - ucs->dr_ctrl.bRequest = req; - ucs->dr_ctrl.wValue = cpu_to_le16(val); - ucs->dr_ctrl.wIndex = 0; - ucs->dr_ctrl.wLength = 0; - usb_fill_control_urb(ucs->urb_ctrl, ucs->udev, - usb_sndctrlpipe(ucs->udev, 0), - (unsigned char *) &ucs->dr_ctrl, NULL, 0, - write_ctrl_callback, ucs); - ucs->retry_ctrl = 0; - ret = usb_submit_urb(ucs->urb_ctrl, GFP_ATOMIC); - if (unlikely(ret)) { - dev_err(bcs->cs->dev, "could not submit request 0x%02x: %s\n", - req, get_usb_rcmsg(ret)); - spin_unlock_irqrestore(&ucs->lock, flags); - return ret; - } - ucs->pending = req; - - if (timeout > 0) { - gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); - mod_timer(&ucs->timer_ctrl, jiffies + timeout * HZ / 10); - } - - spin_unlock_irqrestore(&ucs->lock, flags); - return 0; -} - -/* gigaset_init_bchannel - * called by common.c to connect a B channel - * initialize isochronous I/O and tell the Gigaset base to open the channel - * argument: - * B channel control structure - * return value: - * 0 on success, error code < 0 on error - */ -static int gigaset_init_bchannel(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - int req, ret; - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - if (unlikely(!cs->connected)) { - gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); - spin_unlock_irqrestore(&cs->lock, flags); - return -ENODEV; - } - - if (cs->hw.bas->basstate & BS_SUSPEND) { - dev_notice(cs->dev, - "not starting isoc I/O, suspend in progress\n"); - spin_unlock_irqrestore(&cs->lock, flags); - return -EHOSTUNREACH; - } - - ret = starturbs(bcs); - if (ret < 0) { - spin_unlock_irqrestore(&cs->lock, flags); - dev_err(cs->dev, - "could not start isoc I/O for channel B%d: %s\n", - bcs->channel + 1, - ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); - if (ret != -ENODEV) - error_hangup(bcs); - return ret; - } - - req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; - ret = req_submit(bcs, req, 0, BAS_TIMEOUT); - if (ret < 0) { - dev_err(cs->dev, "could not open channel B%d\n", - bcs->channel + 1); - stopurbs(bcs->hw.bas); - } - - spin_unlock_irqrestore(&cs->lock, flags); - if (ret < 0 && ret != -ENODEV) - error_hangup(bcs); - return ret; -} - -/* gigaset_close_bchannel - * called by common.c to disconnect a B channel - * tell the Gigaset base to close the channel - * stopping isochronous I/O and LL notification will be done when the - * acknowledgement for the close arrives - * argument: - * B channel control structure - * return value: - * 0 on success, error code < 0 on error - */ -static int gigaset_close_bchannel(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - int req, ret; - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - if (unlikely(!cs->connected)) { - spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); - return -ENODEV; - } - - if (!(cs->hw.bas->basstate & (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { - /* channel not running: just signal common.c */ - spin_unlock_irqrestore(&cs->lock, flags); - gigaset_bchannel_down(bcs); - return 0; - } - - /* channel running: tell device to close it */ - req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; - ret = req_submit(bcs, req, 0, BAS_TIMEOUT); - if (ret < 0) - dev_err(cs->dev, "closing channel B%d failed\n", - bcs->channel + 1); - - spin_unlock_irqrestore(&cs->lock, flags); - return ret; -} - -/* Device Operations */ -/* ================= */ - -/* complete_cb - * unqueue first command buffer from queue, waking any sleepers - * must be called with cs->cmdlock held - * parameter: - * cs controller state structure - */ -static void complete_cb(struct cardstate *cs) -{ - struct cmdbuf_t *cb = cs->cmdbuf; - - /* unqueue completed buffer */ - cs->cmdbytes -= cs->curlen; - gig_dbg(DEBUG_OUTPUT, "write_command: sent %u bytes, %u left", - cs->curlen, cs->cmdbytes); - if (cb->next != NULL) { - cs->cmdbuf = cb->next; - cs->cmdbuf->prev = NULL; - cs->curlen = cs->cmdbuf->len; - } else { - cs->cmdbuf = NULL; - cs->lastcmdbuf = NULL; - cs->curlen = 0; - } - - if (cb->wake_tasklet) - tasklet_schedule(cb->wake_tasklet); - - kfree(cb); -} - -/* write_command_callback - * USB completion handler for AT command transmission - * called by the USB subsystem in interrupt context - * parameter: - * urb USB request block of completed request - * urb->context = controller state structure - */ -static void write_command_callback(struct urb *urb) -{ - struct cardstate *cs = urb->context; - struct bas_cardstate *ucs = cs->hw.bas; - int status = urb->status; - unsigned long flags; - - update_basstate(ucs, 0, BS_ATWRPEND); - wake_up(&ucs->waitqueue); - - /* check status */ - switch (status) { - case 0: /* normal completion */ - break; - case -ENOENT: /* cancelled */ - case -ECONNRESET: /* cancelled (async) */ - case -EINPROGRESS: /* pending */ - case -ENODEV: /* device removed */ - case -ESHUTDOWN: /* device shut down */ - /* ignore silently */ - gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(status)); - return; - default: /* any failure */ - if (++ucs->retry_cmd_out > BAS_RETRY) { - dev_warn(cs->dev, - "command write: %s, " - "giving up after %d retries\n", - get_usb_statmsg(status), - ucs->retry_cmd_out); - break; - } - if (ucs->basstate & BS_SUSPEND) { - dev_warn(cs->dev, - "command write: %s, " - "won't retry - suspend requested\n", - get_usb_statmsg(status)); - break; - } - if (cs->cmdbuf == NULL) { - dev_warn(cs->dev, - "command write: %s, " - "cannot retry - cmdbuf gone\n", - get_usb_statmsg(status)); - break; - } - dev_notice(cs->dev, "command write: %s, retry %d\n", - get_usb_statmsg(status), ucs->retry_cmd_out); - if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0) - /* resubmitted - bypass regular exit block */ - return; - /* command send failed, assume base still waiting */ - update_basstate(ucs, BS_ATREADY, 0); - } - - spin_lock_irqsave(&cs->cmdlock, flags); - if (cs->cmdbuf != NULL) - complete_cb(cs); - spin_unlock_irqrestore(&cs->cmdlock, flags); -} - -/* atrdy_timeout - * timeout routine for AT command transmission - * argument: - * controller state structure - */ -static void atrdy_timeout(struct timer_list *t) -{ - struct bas_cardstate *ucs = from_timer(ucs, t, timer_atrdy); - struct cardstate *cs = ucs->cs; - - dev_warn(cs->dev, "timeout waiting for HD_READY_SEND_ATDATA\n"); - - /* fake the missing signal - what else can I do? */ - update_basstate(ucs, BS_ATREADY, BS_ATTIMER); - start_cbsend(cs); -} - -/* atwrite_submit - * submit an HD_WRITE_ATMESSAGE command URB - * parameters: - * cs controller state structure - * buf buffer containing command to send - * len length of command to send - * return value: - * 0 on success - * -EBUSY if another request is pending - * any URB submission error code - */ -static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) -{ - struct bas_cardstate *ucs = cs->hw.bas; - int rc; - - gig_dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len); - - if (update_basstate(ucs, BS_ATWRPEND, 0) & BS_ATWRPEND) { - dev_err(cs->dev, - "could not submit HD_WRITE_ATMESSAGE: URB busy\n"); - return -EBUSY; - } - - ucs->dr_cmd_out.bRequestType = OUT_VENDOR_REQ; - ucs->dr_cmd_out.bRequest = HD_WRITE_ATMESSAGE; - ucs->dr_cmd_out.wValue = 0; - ucs->dr_cmd_out.wIndex = 0; - ucs->dr_cmd_out.wLength = cpu_to_le16(len); - usb_fill_control_urb(ucs->urb_cmd_out, ucs->udev, - usb_sndctrlpipe(ucs->udev, 0), - (unsigned char *) &ucs->dr_cmd_out, buf, len, - write_command_callback, cs); - rc = usb_submit_urb(ucs->urb_cmd_out, GFP_ATOMIC); - if (unlikely(rc)) { - update_basstate(ucs, 0, BS_ATWRPEND); - dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n", - get_usb_rcmsg(rc)); - return rc; - } - - /* submitted successfully, start timeout if necessary */ - if (!(update_basstate(ucs, BS_ATTIMER, BS_ATREADY) & BS_ATTIMER)) { - gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs", - ATRDY_TIMEOUT); - mod_timer(&ucs->timer_atrdy, jiffies + ATRDY_TIMEOUT * HZ / 10); - } - return 0; -} - -/* start_cbsend - * start transmission of AT command queue if necessary - * parameter: - * cs controller state structure - * return value: - * 0 on success - * error code < 0 on error - */ -static int start_cbsend(struct cardstate *cs) -{ - struct cmdbuf_t *cb; - struct bas_cardstate *ucs = cs->hw.bas; - unsigned long flags; - int rc; - int retval = 0; - - /* check if suspend requested */ - if (ucs->basstate & BS_SUSPEND) { - gig_dbg(DEBUG_OUTPUT, "suspending"); - return -EHOSTUNREACH; - } - - /* check if AT channel is open */ - if (!(ucs->basstate & BS_ATOPEN)) { - gig_dbg(DEBUG_OUTPUT, "AT channel not open"); - rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); - if (rc < 0) { - /* flush command queue */ - spin_lock_irqsave(&cs->cmdlock, flags); - while (cs->cmdbuf != NULL) - complete_cb(cs); - spin_unlock_irqrestore(&cs->cmdlock, flags); - } - return rc; - } - - /* try to send first command in queue */ - spin_lock_irqsave(&cs->cmdlock, flags); - - while ((cb = cs->cmdbuf) != NULL && (ucs->basstate & BS_ATREADY)) { - ucs->retry_cmd_out = 0; - rc = atwrite_submit(cs, cb->buf, cb->len); - if (unlikely(rc)) { - retval = rc; - complete_cb(cs); - } - } - - spin_unlock_irqrestore(&cs->cmdlock, flags); - return retval; -} - -/* gigaset_write_cmd - * This function is called by the device independent part of the driver - * to transmit an AT command string to the Gigaset device. - * It encapsulates the device specific method for transmission over the - * direct USB connection to the base. - * The command string is added to the queue of commands to send, and - * USB transmission is started if necessary. - * parameters: - * cs controller state structure - * cb command buffer structure - * return value: - * number of bytes queued on success - * error code < 0 on error - */ -static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb) -{ - unsigned long flags; - int rc; - - gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? - DEBUG_TRANSCMD : DEBUG_LOCKCMD, - "CMD Transmit", cb->len, cb->buf); - - /* translate "+++" escape sequence sent as a single separate command - * into "close AT channel" command for error recovery - * The next command will reopen the AT channel automatically. - */ - if (cb->len == 3 && !memcmp(cb->buf, "+++", 3)) { - /* If an HD_RECEIVEATDATA_ACK message remains unhandled - * because of an error, the base never sends another one. - * The response channel is thus effectively blocked. - * Closing and reopening the AT channel does *not* clear - * this condition. - * As a stopgap measure, submit a zero-length AT read - * before closing the AT channel. This has the undocumented - * effect of triggering a new HD_RECEIVEATDATA_ACK message - * from the base if necessary. - * The subsequent AT channel close then discards any pending - * messages. - */ - spin_lock_irqsave(&cs->lock, flags); - if (!(cs->hw.bas->basstate & BS_ATRDPEND)) { - kfree(cs->hw.bas->rcvbuf); - cs->hw.bas->rcvbuf = NULL; - cs->hw.bas->rcvbuf_size = 0; - cs->hw.bas->retry_cmd_in = 0; - atread_submit(cs, 0); - } - spin_unlock_irqrestore(&cs->lock, flags); - - rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT); - if (cb->wake_tasklet) - tasklet_schedule(cb->wake_tasklet); - if (!rc) - rc = cb->len; - kfree(cb); - return rc; - } - - spin_lock_irqsave(&cs->cmdlock, flags); - cb->prev = cs->lastcmdbuf; - if (cs->lastcmdbuf) - cs->lastcmdbuf->next = cb; - else { - cs->cmdbuf = cb; - cs->curlen = cb->len; - } - cs->cmdbytes += cb->len; - cs->lastcmdbuf = cb; - spin_unlock_irqrestore(&cs->cmdlock, flags); - - spin_lock_irqsave(&cs->lock, flags); - if (unlikely(!cs->connected)) { - spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); - /* flush command queue */ - spin_lock_irqsave(&cs->cmdlock, flags); - while (cs->cmdbuf != NULL) - complete_cb(cs); - spin_unlock_irqrestore(&cs->cmdlock, flags); - return -ENODEV; - } - rc = start_cbsend(cs); - spin_unlock_irqrestore(&cs->lock, flags); - return rc < 0 ? rc : cb->len; -} - -/* gigaset_write_room - * tty_driver.write_room interface routine - * return number of characters the driver will accept to be written via - * gigaset_write_cmd - * parameter: - * controller state structure - * return value: - * number of characters - */ -static int gigaset_write_room(struct cardstate *cs) -{ - return IF_WRITEBUF; -} - -/* gigaset_chars_in_buffer - * tty_driver.chars_in_buffer interface routine - * return number of characters waiting to be sent - * parameter: - * controller state structure - * return value: - * number of characters - */ -static int gigaset_chars_in_buffer(struct cardstate *cs) -{ - return cs->cmdbytes; -} - -/* gigaset_brkchars - * implementation of ioctl(GIGASET_BRKCHARS) - * parameter: - * controller state structure - * return value: - * -EINVAL (unimplemented function) - */ -static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) -{ - return -EINVAL; -} - - -/* Device Initialization/Shutdown */ -/* ============================== */ - -/* Free hardware dependent part of the B channel structure - * parameter: - * bcs B channel structure - */ -static void gigaset_freebcshw(struct bc_state *bcs) -{ - struct bas_bc_state *ubc = bcs->hw.bas; - int i; - - if (!ubc) - return; - - /* kill URBs and tasklets before freeing - better safe than sorry */ - ubc->running = 0; - gig_dbg(DEBUG_INIT, "%s: killing isoc URBs", __func__); - for (i = 0; i < BAS_OUTURBS; ++i) { - usb_kill_urb(ubc->isoouturbs[i].urb); - usb_free_urb(ubc->isoouturbs[i].urb); - } - for (i = 0; i < BAS_INURBS; ++i) { - usb_kill_urb(ubc->isoinurbs[i]); - usb_free_urb(ubc->isoinurbs[i]); - } - tasklet_kill(&ubc->sent_tasklet); - tasklet_kill(&ubc->rcvd_tasklet); - kfree(ubc->isooutbuf); - kfree(ubc); - bcs->hw.bas = NULL; -} - -/* Initialize hardware dependent part of the B channel structure - * parameter: - * bcs B channel structure - * return value: - * 0 on success, error code < 0 on failure - */ -static int gigaset_initbcshw(struct bc_state *bcs) -{ - int i; - struct bas_bc_state *ubc; - - bcs->hw.bas = ubc = kmalloc(sizeof(struct bas_bc_state), GFP_KERNEL); - if (!ubc) { - pr_err("out of memory\n"); - return -ENOMEM; - } - - ubc->running = 0; - atomic_set(&ubc->corrbytes, 0); - spin_lock_init(&ubc->isooutlock); - for (i = 0; i < BAS_OUTURBS; ++i) { - ubc->isoouturbs[i].urb = NULL; - ubc->isoouturbs[i].bcs = bcs; - } - ubc->isooutdone = ubc->isooutfree = ubc->isooutovfl = NULL; - ubc->numsub = 0; - ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL); - if (!ubc->isooutbuf) { - pr_err("out of memory\n"); - kfree(ubc); - bcs->hw.bas = NULL; - return -ENOMEM; - } - tasklet_init(&ubc->sent_tasklet, - write_iso_tasklet, (unsigned long) bcs); - - spin_lock_init(&ubc->isoinlock); - for (i = 0; i < BAS_INURBS; ++i) - ubc->isoinurbs[i] = NULL; - ubc->isoindone = NULL; - ubc->loststatus = -EINPROGRESS; - ubc->isoinlost = 0; - ubc->seqlen = 0; - ubc->inbyte = 0; - ubc->inbits = 0; - ubc->goodbytes = 0; - ubc->alignerrs = 0; - ubc->fcserrs = 0; - ubc->frameerrs = 0; - ubc->giants = 0; - ubc->runts = 0; - ubc->aborts = 0; - ubc->shared0s = 0; - ubc->stolen0s = 0; - tasklet_init(&ubc->rcvd_tasklet, - read_iso_tasklet, (unsigned long) bcs); - return 0; -} - -static void gigaset_reinitbcshw(struct bc_state *bcs) -{ - struct bas_bc_state *ubc = bcs->hw.bas; - - bcs->hw.bas->running = 0; - atomic_set(&bcs->hw.bas->corrbytes, 0); - bcs->hw.bas->numsub = 0; - spin_lock_init(&ubc->isooutlock); - spin_lock_init(&ubc->isoinlock); - ubc->loststatus = -EINPROGRESS; -} - -static void gigaset_freecshw(struct cardstate *cs) -{ - /* timers, URBs and rcvbuf are disposed of in disconnect */ - kfree(cs->hw.bas->int_in_buf); - kfree(cs->hw.bas); - cs->hw.bas = NULL; -} - -/* Initialize hardware dependent part of the cardstate structure - * parameter: - * cs cardstate structure - * return value: - * 0 on success, error code < 0 on failure - */ -static int gigaset_initcshw(struct cardstate *cs) -{ - struct bas_cardstate *ucs; - - cs->hw.bas = ucs = kzalloc(sizeof(*ucs), GFP_KERNEL); - if (!ucs) { - pr_err("out of memory\n"); - return -ENOMEM; - } - ucs->int_in_buf = kmalloc(IP_MSGSIZE, GFP_KERNEL); - if (!ucs->int_in_buf) { - kfree(ucs); - pr_err("out of memory\n"); - return -ENOMEM; - } - - spin_lock_init(&ucs->lock); - ucs->cs = cs; - timer_setup(&ucs->timer_ctrl, req_timeout, 0); - timer_setup(&ucs->timer_atrdy, atrdy_timeout, 0); - timer_setup(&ucs->timer_cmd_in, cmd_in_timeout, 0); - timer_setup(&ucs->timer_int_in, int_in_resubmit, 0); - init_waitqueue_head(&ucs->waitqueue); - INIT_WORK(&ucs->int_in_wq, int_in_work); - - return 0; -} - -/* freeurbs - * unlink and deallocate all URBs unconditionally - * caller must make sure that no commands are still in progress - * parameter: - * cs controller state structure - */ -static void freeurbs(struct cardstate *cs) -{ - struct bas_cardstate *ucs = cs->hw.bas; - struct bas_bc_state *ubc; - int i, j; - - gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__); - for (j = 0; j < BAS_CHANNELS; ++j) { - ubc = cs->bcs[j].hw.bas; - for (i = 0; i < BAS_OUTURBS; ++i) { - usb_kill_urb(ubc->isoouturbs[i].urb); - usb_free_urb(ubc->isoouturbs[i].urb); - ubc->isoouturbs[i].urb = NULL; - } - for (i = 0; i < BAS_INURBS; ++i) { - usb_kill_urb(ubc->isoinurbs[i]); - usb_free_urb(ubc->isoinurbs[i]); - ubc->isoinurbs[i] = NULL; - } - } - usb_kill_urb(ucs->urb_int_in); - usb_free_urb(ucs->urb_int_in); - ucs->urb_int_in = NULL; - usb_kill_urb(ucs->urb_cmd_out); - usb_free_urb(ucs->urb_cmd_out); - ucs->urb_cmd_out = NULL; - usb_kill_urb(ucs->urb_cmd_in); - usb_free_urb(ucs->urb_cmd_in); - ucs->urb_cmd_in = NULL; - usb_kill_urb(ucs->urb_ctrl); - usb_free_urb(ucs->urb_ctrl); - ucs->urb_ctrl = NULL; -} - -/* gigaset_probe - * This function is called when a new USB device is connected. - * It checks whether the new device is handled by this driver. - */ -static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_host_interface *hostif; - struct usb_device *udev = interface_to_usbdev(interface); - struct cardstate *cs = NULL; - struct bas_cardstate *ucs = NULL; - struct bas_bc_state *ubc; - struct usb_endpoint_descriptor *endpoint; - int i, j; - int rc; - - gig_dbg(DEBUG_INIT, - "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", - __func__, le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - /* set required alternate setting */ - hostif = interface->cur_altsetting; - if (hostif->desc.bAlternateSetting != 3) { - gig_dbg(DEBUG_INIT, - "%s: wrong alternate setting %d - trying to switch", - __func__, hostif->desc.bAlternateSetting); - if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) - < 0) { - dev_warn(&udev->dev, "usb_set_interface failed, " - "device %d interface %d altsetting %d\n", - udev->devnum, hostif->desc.bInterfaceNumber, - hostif->desc.bAlternateSetting); - return -ENODEV; - } - hostif = interface->cur_altsetting; - } - - /* Reject application specific interfaces - */ - if (hostif->desc.bInterfaceClass != 255) { - dev_warn(&udev->dev, "%s: bInterfaceClass == %d\n", - __func__, hostif->desc.bInterfaceClass); - return -ENODEV; - } - - if (hostif->desc.bNumEndpoints < 1) - return -ENODEV; - - dev_info(&udev->dev, - "%s: Device matched (Vendor: 0x%x, Product: 0x%x)\n", - __func__, le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - /* allocate memory for our device state and initialize it */ - cs = gigaset_initcs(driver, BAS_CHANNELS, 0, 0, cidmode, - GIGASET_MODULENAME); - if (!cs) - return -ENODEV; - ucs = cs->hw.bas; - - /* save off device structure ptrs for later use */ - usb_get_dev(udev); - ucs->udev = udev; - ucs->interface = interface; - cs->dev = &interface->dev; - - /* allocate URBs: - * - one for the interrupt pipe - * - three for the different uses of the default control pipe - * - three for each isochronous pipe - */ - if (!(ucs->urb_int_in = usb_alloc_urb(0, GFP_KERNEL)) || - !(ucs->urb_cmd_in = usb_alloc_urb(0, GFP_KERNEL)) || - !(ucs->urb_cmd_out = usb_alloc_urb(0, GFP_KERNEL)) || - !(ucs->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL))) - goto allocerr; - - for (j = 0; j < BAS_CHANNELS; ++j) { - ubc = cs->bcs[j].hw.bas; - for (i = 0; i < BAS_OUTURBS; ++i) - if (!(ubc->isoouturbs[i].urb = - usb_alloc_urb(BAS_NUMFRAMES, GFP_KERNEL))) - goto allocerr; - for (i = 0; i < BAS_INURBS; ++i) - if (!(ubc->isoinurbs[i] = - usb_alloc_urb(BAS_NUMFRAMES, GFP_KERNEL))) - goto allocerr; - } - - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; - - /* Fill the interrupt urb and send it to the core */ - endpoint = &hostif->endpoint[0].desc; - usb_fill_int_urb(ucs->urb_int_in, udev, - usb_rcvintpipe(udev, - usb_endpoint_num(endpoint)), - ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs, - endpoint->bInterval); - rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL); - if (rc != 0) { - dev_err(cs->dev, "could not submit interrupt URB: %s\n", - get_usb_rcmsg(rc)); - goto error; - } - ucs->retry_int_in = 0; - - /* tell the device that the driver is ready */ - rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0); - if (rc != 0) - goto error; - - /* tell common part that the device is ready */ - if (startmode == SM_LOCKED) - cs->mstate = MS_LOCKED; - - /* save address of controller structure */ - usb_set_intfdata(interface, cs); - - rc = gigaset_start(cs); - if (rc < 0) - goto error; - - return 0; - -allocerr: - dev_err(cs->dev, "could not allocate URBs\n"); - rc = -ENOMEM; -error: - freeurbs(cs); - usb_set_intfdata(interface, NULL); - usb_put_dev(udev); - gigaset_freecs(cs); - return rc; -} - -/* gigaset_disconnect - * This function is called when the Gigaset base is unplugged. - */ -static void gigaset_disconnect(struct usb_interface *interface) -{ - struct cardstate *cs; - struct bas_cardstate *ucs; - int j; - - cs = usb_get_intfdata(interface); - - ucs = cs->hw.bas; - - dev_info(cs->dev, "disconnecting Gigaset base\n"); - - /* mark base as not ready, all channels disconnected */ - ucs->basstate = 0; - - /* tell LL all channels are down */ - for (j = 0; j < BAS_CHANNELS; ++j) - gigaset_bchannel_down(cs->bcs + j); - - /* stop driver (common part) */ - gigaset_stop(cs); - - /* stop delayed work and URBs, free ressources */ - del_timer_sync(&ucs->timer_ctrl); - del_timer_sync(&ucs->timer_atrdy); - del_timer_sync(&ucs->timer_cmd_in); - del_timer_sync(&ucs->timer_int_in); - cancel_work_sync(&ucs->int_in_wq); - freeurbs(cs); - usb_set_intfdata(interface, NULL); - kfree(ucs->rcvbuf); - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; - usb_put_dev(ucs->udev); - ucs->interface = NULL; - ucs->udev = NULL; - cs->dev = NULL; - gigaset_freecs(cs); -} - -/* gigaset_suspend - * This function is called before the USB connection is suspended - * or before the USB device is reset. - * In the latter case, message == PMSG_ON. - */ -static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct cardstate *cs = usb_get_intfdata(intf); - struct bas_cardstate *ucs = cs->hw.bas; - int rc; - - /* set suspend flag; this stops AT command/response traffic */ - if (update_basstate(ucs, BS_SUSPEND, 0) & BS_SUSPEND) { - gig_dbg(DEBUG_SUSPEND, "already suspended"); - return 0; - } - - /* wait a bit for blocking conditions to go away */ - rc = wait_event_timeout(ucs->waitqueue, - !(ucs->basstate & - (BS_B1OPEN | BS_B2OPEN | BS_ATRDPEND | BS_ATWRPEND)), - BAS_TIMEOUT * HZ / 10); - gig_dbg(DEBUG_SUSPEND, "wait_event_timeout() -> %d", rc); - - /* check for conditions preventing suspend */ - if (ucs->basstate & (BS_B1OPEN | BS_B2OPEN | BS_ATRDPEND | BS_ATWRPEND)) { - dev_warn(cs->dev, "cannot suspend:\n"); - if (ucs->basstate & BS_B1OPEN) - dev_warn(cs->dev, " B channel 1 open\n"); - if (ucs->basstate & BS_B2OPEN) - dev_warn(cs->dev, " B channel 2 open\n"); - if (ucs->basstate & BS_ATRDPEND) - dev_warn(cs->dev, " receiving AT reply\n"); - if (ucs->basstate & BS_ATWRPEND) - dev_warn(cs->dev, " sending AT command\n"); - update_basstate(ucs, 0, BS_SUSPEND); - return -EBUSY; - } - - /* close AT channel if open */ - if (ucs->basstate & BS_ATOPEN) { - gig_dbg(DEBUG_SUSPEND, "closing AT channel"); - rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, 0); - if (rc) { - update_basstate(ucs, 0, BS_SUSPEND); - return rc; - } - wait_event_timeout(ucs->waitqueue, !ucs->pending, - BAS_TIMEOUT * HZ / 10); - /* in case of timeout, proceed anyway */ - } - - /* kill all URBs and delayed work that might still be pending */ - usb_kill_urb(ucs->urb_ctrl); - usb_kill_urb(ucs->urb_int_in); - del_timer_sync(&ucs->timer_ctrl); - del_timer_sync(&ucs->timer_atrdy); - del_timer_sync(&ucs->timer_cmd_in); - del_timer_sync(&ucs->timer_int_in); - - /* don't try to cancel int_in_wq from within reset as it - * might be the one requesting the reset - */ - if (message.event != PM_EVENT_ON) - cancel_work_sync(&ucs->int_in_wq); - - gig_dbg(DEBUG_SUSPEND, "suspend complete"); - return 0; -} - -/* gigaset_resume - * This function is called after the USB connection has been resumed. - */ -static int gigaset_resume(struct usb_interface *intf) -{ - struct cardstate *cs = usb_get_intfdata(intf); - struct bas_cardstate *ucs = cs->hw.bas; - int rc; - - /* resubmit interrupt URB for spontaneous messages from base */ - rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL); - if (rc) { - dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", - get_usb_rcmsg(rc)); - return rc; - } - ucs->retry_int_in = 0; - - /* clear suspend flag to reallow activity */ - update_basstate(ucs, 0, BS_SUSPEND); - - gig_dbg(DEBUG_SUSPEND, "resume complete"); - return 0; -} - -/* gigaset_pre_reset - * This function is called before the USB connection is reset. - */ -static int gigaset_pre_reset(struct usb_interface *intf) -{ - /* handle just like suspend */ - return gigaset_suspend(intf, PMSG_ON); -} - -/* gigaset_post_reset - * This function is called after the USB connection has been reset. - */ -static int gigaset_post_reset(struct usb_interface *intf) -{ - /* FIXME: send HD_DEVICE_INIT_ACK? */ - - /* resume operations */ - return gigaset_resume(intf); -} - - -static const struct gigaset_ops gigops = { - .write_cmd = gigaset_write_cmd, - .write_room = gigaset_write_room, - .chars_in_buffer = gigaset_chars_in_buffer, - .brkchars = gigaset_brkchars, - .init_bchannel = gigaset_init_bchannel, - .close_bchannel = gigaset_close_bchannel, - .initbcshw = gigaset_initbcshw, - .freebcshw = gigaset_freebcshw, - .reinitbcshw = gigaset_reinitbcshw, - .initcshw = gigaset_initcshw, - .freecshw = gigaset_freecshw, - .set_modem_ctrl = gigaset_set_modem_ctrl, - .baud_rate = gigaset_baud_rate, - .set_line_ctrl = gigaset_set_line_ctrl, - .send_skb = gigaset_isoc_send_skb, - .handle_input = gigaset_isoc_input, -}; - -/* bas_gigaset_init - * This function is called after the kernel module is loaded. - */ -static int __init bas_gigaset_init(void) -{ - int result; - - /* allocate memory for our driver state and initialize it */ - driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - &gigops, THIS_MODULE); - if (driver == NULL) - goto error; - - /* register this driver with the USB subsystem */ - result = usb_register(&gigaset_usb_driver); - if (result < 0) { - pr_err("error %d registering USB driver\n", -result); - goto error; - } - - pr_info(DRIVER_DESC "\n"); - return 0; - -error: - if (driver) - gigaset_freedriver(driver); - driver = NULL; - return -1; -} - -/* bas_gigaset_exit - * This function is called before the kernel module is unloaded. - */ -static void __exit bas_gigaset_exit(void) -{ - struct bas_cardstate *ucs; - int i; - - gigaset_blockdriver(driver); /* => probe will fail - * => no gigaset_start any more - */ - - /* stop all connected devices */ - for (i = 0; i < driver->minors; i++) { - if (gigaset_shutdown(driver->cs + i) < 0) - continue; /* no device */ - /* from now on, no isdn callback should be possible */ - - /* close all still open channels */ - ucs = driver->cs[i].hw.bas; - if (ucs->basstate & BS_B1OPEN) { - gig_dbg(DEBUG_INIT, "closing B1 channel"); - usb_control_msg(ucs->udev, - usb_sndctrlpipe(ucs->udev, 0), - HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, - 0, 0, NULL, 0, BAS_TIMEOUT); - } - if (ucs->basstate & BS_B2OPEN) { - gig_dbg(DEBUG_INIT, "closing B2 channel"); - usb_control_msg(ucs->udev, - usb_sndctrlpipe(ucs->udev, 0), - HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, - 0, 0, NULL, 0, BAS_TIMEOUT); - } - if (ucs->basstate & BS_ATOPEN) { - gig_dbg(DEBUG_INIT, "closing AT channel"); - usb_control_msg(ucs->udev, - usb_sndctrlpipe(ucs->udev, 0), - HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, - 0, 0, NULL, 0, BAS_TIMEOUT); - } - ucs->basstate = 0; - } - - /* deregister this driver with the USB subsystem */ - usb_deregister(&gigaset_usb_driver); - /* this will call the disconnect-callback */ - /* from now on, no disconnect/probe callback should be running */ - - gigaset_freedriver(driver); - driver = NULL; -} - - -module_init(bas_gigaset_init); -module_exit(bas_gigaset_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/isdn/gigaset/capi.c b/drivers/staging/isdn/gigaset/capi.c deleted file mode 100644 index 83d7dd48c61d..000000000000 --- a/drivers/staging/isdn/gigaset/capi.c +++ /dev/null @@ -1,2517 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Kernel CAPI interface for the Gigaset driver - * - * Copyright (c) 2009 by Tilman Schmidt . - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include -#include -#include -#include -#include -#include - -/* missing from kernelcapi.h */ -#define CapiNcpiNotSupportedByProtocol 0x0001 -#define CapiFlagsNotSupportedByProtocol 0x0002 -#define CapiAlertAlreadySent 0x0003 -#define CapiFacilitySpecificFunctionNotSupported 0x3011 - -/* missing from capicmd.h */ -#define CAPI_CONNECT_IND_BASELEN (CAPI_MSG_BASELEN + 4 + 2 + 8 * 1) -#define CAPI_CONNECT_ACTIVE_IND_BASELEN (CAPI_MSG_BASELEN + 4 + 3 * 1) -#define CAPI_CONNECT_B3_IND_BASELEN (CAPI_MSG_BASELEN + 4 + 1) -#define CAPI_CONNECT_B3_ACTIVE_IND_BASELEN (CAPI_MSG_BASELEN + 4 + 1) -#define CAPI_DATA_B3_REQ_LEN64 (CAPI_MSG_BASELEN + 4 + 4 + 2 + 2 + 2 + 8) -#define CAPI_DATA_B3_CONF_LEN (CAPI_MSG_BASELEN + 4 + 2 + 2) -#define CAPI_DISCONNECT_IND_LEN (CAPI_MSG_BASELEN + 4 + 2) -#define CAPI_DISCONNECT_B3_IND_BASELEN (CAPI_MSG_BASELEN + 4 + 2 + 1) -#define CAPI_FACILITY_CONF_BASELEN (CAPI_MSG_BASELEN + 4 + 2 + 2 + 1) -/* most _CONF messages contain only Controller/PLCI/NCCI and Info parameters */ -#define CAPI_STDCONF_LEN (CAPI_MSG_BASELEN + 4 + 2) - -#define CAPI_FACILITY_HANDSET 0x0000 -#define CAPI_FACILITY_DTMF 0x0001 -#define CAPI_FACILITY_V42BIS 0x0002 -#define CAPI_FACILITY_SUPPSVC 0x0003 -#define CAPI_FACILITY_WAKEUP 0x0004 -#define CAPI_FACILITY_LI 0x0005 - -#define CAPI_SUPPSVC_GETSUPPORTED 0x0000 -#define CAPI_SUPPSVC_LISTEN 0x0001 - -/* missing from capiutil.h */ -#define CAPIMSG_PLCI_PART(m) CAPIMSG_U8(m, 9) -#define CAPIMSG_NCCI_PART(m) CAPIMSG_U16(m, 10) -#define CAPIMSG_HANDLE_REQ(m) CAPIMSG_U16(m, 18) /* DATA_B3_REQ/_IND only! */ -#define CAPIMSG_FLAGS(m) CAPIMSG_U16(m, 20) -#define CAPIMSG_SETCONTROLLER(m, contr) capimsg_setu8(m, 8, contr) -#define CAPIMSG_SETPLCI_PART(m, plci) capimsg_setu8(m, 9, plci) -#define CAPIMSG_SETNCCI_PART(m, ncci) capimsg_setu16(m, 10, ncci) -#define CAPIMSG_SETFLAGS(m, flags) capimsg_setu16(m, 20, flags) - -/* parameters with differing location in DATA_B3_CONF/_RESP: */ -#define CAPIMSG_SETHANDLE_CONF(m, handle) capimsg_setu16(m, 12, handle) -#define CAPIMSG_SETINFO_CONF(m, info) capimsg_setu16(m, 14, info) - -/* Flags (DATA_B3_REQ/_IND) */ -#define CAPI_FLAGS_DELIVERY_CONFIRMATION 0x04 -#define CAPI_FLAGS_RESERVED (~0x1f) - -/* buffer sizes */ -#define MAX_BC_OCTETS 11 -#define MAX_HLC_OCTETS 3 -#define MAX_NUMBER_DIGITS 20 -#define MAX_FMT_IE_LEN 20 - -/* values for bcs->apconnstate */ -#define APCONN_NONE 0 /* inactive/listening */ -#define APCONN_SETUP 1 /* connecting */ -#define APCONN_ACTIVE 2 /* B channel up */ - -/* registered application data structure */ -struct gigaset_capi_appl { - struct list_head ctrlist; - struct gigaset_capi_appl *bcnext; - u16 id; - struct capi_register_params rp; - u16 nextMessageNumber; - u32 listenInfoMask; - u32 listenCIPmask; -}; - -/* CAPI specific controller data structure */ -struct gigaset_capi_ctr { - struct capi_ctr ctr; - struct list_head appls; - struct sk_buff_head sendqueue; - atomic_t sendqlen; - /* two _cmsg structures possibly used concurrently: */ - _cmsg hcmsg; /* for message composition triggered from hardware */ - _cmsg acmsg; /* for dissection of messages sent from application */ - u8 bc_buf[MAX_BC_OCTETS + 1]; - u8 hlc_buf[MAX_HLC_OCTETS + 1]; - u8 cgpty_buf[MAX_NUMBER_DIGITS + 3]; - u8 cdpty_buf[MAX_NUMBER_DIGITS + 2]; -}; - -/* CIP Value table (from CAPI 2.0 standard, ch. 6.1) */ -static struct { - u8 *bc; - u8 *hlc; -} cip2bchlc[] = { - [1] = { "8090A3", NULL }, /* Speech (A-law) */ - [2] = { "8890", NULL }, /* Unrestricted digital information */ - [3] = { "8990", NULL }, /* Restricted digital information */ - [4] = { "9090A3", NULL }, /* 3,1 kHz audio (A-law) */ - [5] = { "9190", NULL }, /* 7 kHz audio */ - [6] = { "9890", NULL }, /* Video */ - [7] = { "88C0C6E6", NULL }, /* Packet mode */ - [8] = { "8890218F", NULL }, /* 56 kbit/s rate adaptation */ - [9] = { "9190A5", NULL }, /* Unrestricted digital information - * with tones/announcements */ - [16] = { "8090A3", "9181" }, /* Telephony */ - [17] = { "9090A3", "9184" }, /* Group 2/3 facsimile */ - [18] = { "8890", "91A1" }, /* Group 4 facsimile Class 1 */ - [19] = { "8890", "91A4" }, /* Teletex service basic and mixed mode - * and Group 4 facsimile service - * Classes II and III */ - [20] = { "8890", "91A8" }, /* Teletex service basic and - * processable mode */ - [21] = { "8890", "91B1" }, /* Teletex service basic mode */ - [22] = { "8890", "91B2" }, /* International interworking for - * Videotex */ - [23] = { "8890", "91B5" }, /* Telex */ - [24] = { "8890", "91B8" }, /* Message Handling Systems - * in accordance with X.400 */ - [25] = { "8890", "91C1" }, /* OSI application - * in accordance with X.200 */ - [26] = { "9190A5", "9181" }, /* 7 kHz telephony */ - [27] = { "9190A5", "916001" }, /* Video telephony, first connection */ - [28] = { "8890", "916002" }, /* Video telephony, second connection */ -}; - -/* - * helper functions - * ================ - */ - -/* - * emit unsupported parameter warning - */ -static inline void ignore_cstruct_param(struct cardstate *cs, _cstruct param, - char *msgname, char *paramname) -{ - if (param && *param) - dev_warn(cs->dev, "%s: ignoring unsupported parameter: %s\n", - msgname, paramname); -} - -/* - * convert an IE from Gigaset hex string to ETSI binary representation - * including length byte - * return value: result length, -1 on error - */ -static int encode_ie(char *in, u8 *out, int maxlen) -{ - int l = 0; - while (*in) { - if (!isxdigit(in[0]) || !isxdigit(in[1]) || l >= maxlen) - return -1; - out[++l] = (hex_to_bin(in[0]) << 4) + hex_to_bin(in[1]); - in += 2; - } - out[0] = l; - return l; -} - -/* - * convert an IE from ETSI binary representation including length byte - * to Gigaset hex string - */ -static void decode_ie(u8 *in, char *out) -{ - int i = *in; - while (i-- > 0) { - /* ToDo: conversion to upper case necessary? */ - *out++ = toupper(hex_asc_hi(*++in)); - *out++ = toupper(hex_asc_lo(*in)); - } -} - -/* - * retrieve application data structure for an application ID - */ -static inline struct gigaset_capi_appl * -get_appl(struct gigaset_capi_ctr *iif, u16 appl) -{ - struct gigaset_capi_appl *ap; - - list_for_each_entry(ap, &iif->appls, ctrlist) - if (ap->id == appl) - return ap; - return NULL; -} - -/* - * dump CAPI message to kernel messages for debugging - */ -static inline void dump_cmsg(enum debuglevel level, const char *tag, _cmsg *p) -{ -#ifdef CONFIG_GIGASET_DEBUG - /* dump at most 20 messages in 20 secs */ - static DEFINE_RATELIMIT_STATE(msg_dump_ratelimit, 20 * HZ, 20); - _cdebbuf *cdb; - - if (!(gigaset_debuglevel & level)) - return; - if (!___ratelimit(&msg_dump_ratelimit, tag)) - return; - - cdb = capi_cmsg2str(p); - if (cdb) { - gig_dbg(level, "%s: [%d] %s", tag, p->ApplId, cdb->buf); - cdebbuf_free(cdb); - } else { - gig_dbg(level, "%s: [%d] %s", tag, p->ApplId, - capi_cmd2str(p->Command, p->Subcommand)); - } -#endif -} - -static inline void dump_rawmsg(enum debuglevel level, const char *tag, - unsigned char *data) -{ -#ifdef CONFIG_GIGASET_DEBUG - char *dbgline; - int i, l; - - if (!(gigaset_debuglevel & level)) - return; - - l = CAPIMSG_LEN(data); - if (l < 12) { - gig_dbg(level, "%s: ??? LEN=%04d", tag, l); - return; - } - gig_dbg(level, "%s: 0x%02x:0x%02x: ID=%03d #0x%04x LEN=%04d NCCI=0x%x", - tag, CAPIMSG_COMMAND(data), CAPIMSG_SUBCOMMAND(data), - CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, - CAPIMSG_CONTROL(data)); - l -= 12; - if (l <= 0) - return; - if (l > 64) - l = 64; /* arbitrary limit */ - dbgline = kmalloc_array(3, l, GFP_ATOMIC); - if (!dbgline) - return; - for (i = 0; i < l; i++) { - dbgline[3 * i] = hex_asc_hi(data[12 + i]); - dbgline[3 * i + 1] = hex_asc_lo(data[12 + i]); - dbgline[3 * i + 2] = ' '; - } - dbgline[3 * l - 1] = '\0'; - gig_dbg(level, " %s", dbgline); - kfree(dbgline); - if (CAPIMSG_COMMAND(data) == CAPI_DATA_B3 && - (CAPIMSG_SUBCOMMAND(data) == CAPI_REQ || - CAPIMSG_SUBCOMMAND(data) == CAPI_IND)) { - l = CAPIMSG_DATALEN(data); - gig_dbg(level, " DataLength=%d", l); - if (l <= 0 || !(gigaset_debuglevel & DEBUG_LLDATA)) - return; - if (l > 64) - l = 64; /* arbitrary limit */ - dbgline = kmalloc_array(3, l, GFP_ATOMIC); - if (!dbgline) - return; - data += CAPIMSG_LEN(data); - for (i = 0; i < l; i++) { - dbgline[3 * i] = hex_asc_hi(data[i]); - dbgline[3 * i + 1] = hex_asc_lo(data[i]); - dbgline[3 * i + 2] = ' '; - } - dbgline[3 * l - 1] = '\0'; - gig_dbg(level, " %s", dbgline); - kfree(dbgline); - } -#endif -} - -/* - * format CAPI IE as string - */ - -#ifdef CONFIG_GIGASET_DEBUG -static const char *format_ie(const char *ie) -{ - static char result[3 * MAX_FMT_IE_LEN]; - int len, count; - char *pout = result; - - if (!ie) - return "NULL"; - - count = len = ie[0]; - if (count > MAX_FMT_IE_LEN) - count = MAX_FMT_IE_LEN - 1; - while (count--) { - *pout++ = hex_asc_hi(*++ie); - *pout++ = hex_asc_lo(*ie); - *pout++ = ' '; - } - if (len > MAX_FMT_IE_LEN) { - *pout++ = '.'; - *pout++ = '.'; - *pout++ = '.'; - } - *--pout = 0; - return result; -} -#endif - -/* - * emit DATA_B3_CONF message - */ -static void send_data_b3_conf(struct cardstate *cs, struct capi_ctr *ctr, - u16 appl, u16 msgid, int channel, - u16 handle, u16 info) -{ - struct sk_buff *cskb; - u8 *msg; - - cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC); - if (!cskb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - /* frequent message, avoid _cmsg overhead */ - msg = __skb_put(cskb, CAPI_DATA_B3_CONF_LEN); - CAPIMSG_SETLEN(msg, CAPI_DATA_B3_CONF_LEN); - CAPIMSG_SETAPPID(msg, appl); - CAPIMSG_SETCOMMAND(msg, CAPI_DATA_B3); - CAPIMSG_SETSUBCOMMAND(msg, CAPI_CONF); - CAPIMSG_SETMSGID(msg, msgid); - CAPIMSG_SETCONTROLLER(msg, ctr->cnr); - CAPIMSG_SETPLCI_PART(msg, channel); - CAPIMSG_SETNCCI_PART(msg, 1); - CAPIMSG_SETHANDLE_CONF(msg, handle); - CAPIMSG_SETINFO_CONF(msg, info); - - /* emit message */ - dump_rawmsg(DEBUG_MCMD, __func__, msg); - capi_ctr_handle_message(ctr, appl, cskb); -} - - -/* - * driver interface functions - * ========================== - */ - -/** - * gigaset_skb_sent() - acknowledge transmission of outgoing skb - * @bcs: B channel descriptor structure. - * @skb: sent data. - * - * Called by hardware module {bas,ser,usb}_gigaset when the data in a - * skb has been successfully sent, for signalling completion to the LL. - */ -void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_ctr *iif = cs->iif; - struct gigaset_capi_appl *ap = bcs->ap; - unsigned char *req = skb_mac_header(dskb); - u16 flags; - - /* update statistics */ - ++bcs->trans_up; - - if (!ap) { - gig_dbg(DEBUG_MCMD, "%s: application gone", __func__); - return; - } - - /* don't send further B3 messages if disconnected */ - if (bcs->apconnstate < APCONN_ACTIVE) { - gig_dbg(DEBUG_MCMD, "%s: disconnected", __func__); - return; - } - - /* - * send DATA_B3_CONF if "delivery confirmation" bit was set in request; - * otherwise it has already been sent by do_data_b3_req() - */ - flags = CAPIMSG_FLAGS(req); - if (flags & CAPI_FLAGS_DELIVERY_CONFIRMATION) - send_data_b3_conf(cs, &iif->ctr, ap->id, CAPIMSG_MSGID(req), - bcs->channel + 1, CAPIMSG_HANDLE_REQ(req), - (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) ? - CapiFlagsNotSupportedByProtocol : - CAPI_NOERROR); -} -EXPORT_SYMBOL_GPL(gigaset_skb_sent); - -/** - * gigaset_skb_rcvd() - pass received skb to LL - * @bcs: B channel descriptor structure. - * @skb: received data. - * - * Called by hardware module {bas,ser,usb}_gigaset when user data has - * been successfully received, for passing to the LL. - * Warning: skb must not be accessed anymore! - */ -void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_ctr *iif = cs->iif; - struct gigaset_capi_appl *ap = bcs->ap; - int len = skb->len; - - /* update statistics */ - bcs->trans_down++; - - if (!ap) { - gig_dbg(DEBUG_MCMD, "%s: application gone", __func__); - dev_kfree_skb_any(skb); - return; - } - - /* don't send further B3 messages if disconnected */ - if (bcs->apconnstate < APCONN_ACTIVE) { - gig_dbg(DEBUG_MCMD, "%s: disconnected", __func__); - dev_kfree_skb_any(skb); - return; - } - - /* - * prepend DATA_B3_IND message to payload - * Parameters: NCCI = 1, all others 0/unused - * frequent message, avoid _cmsg overhead - */ - skb_push(skb, CAPI_DATA_B3_REQ_LEN); - CAPIMSG_SETLEN(skb->data, CAPI_DATA_B3_REQ_LEN); - CAPIMSG_SETAPPID(skb->data, ap->id); - CAPIMSG_SETCOMMAND(skb->data, CAPI_DATA_B3); - CAPIMSG_SETSUBCOMMAND(skb->data, CAPI_IND); - CAPIMSG_SETMSGID(skb->data, ap->nextMessageNumber++); - CAPIMSG_SETCONTROLLER(skb->data, iif->ctr.cnr); - CAPIMSG_SETPLCI_PART(skb->data, bcs->channel + 1); - CAPIMSG_SETNCCI_PART(skb->data, 1); - /* Data parameter not used */ - CAPIMSG_SETDATALEN(skb->data, len); - /* Data handle parameter not used */ - CAPIMSG_SETFLAGS(skb->data, 0); - /* Data64 parameter not present */ - - /* emit message */ - dump_rawmsg(DEBUG_MCMD, __func__, skb->data); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} -EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); - -/** - * gigaset_isdn_rcv_err() - signal receive error - * @bcs: B channel descriptor structure. - * - * Called by hardware module {bas,ser,usb}_gigaset when a receive error - * has occurred, for signalling to the LL. - */ -void gigaset_isdn_rcv_err(struct bc_state *bcs) -{ - /* if currently ignoring packets, just count down */ - if (bcs->ignore) { - bcs->ignore--; - return; - } - - /* update statistics */ - bcs->corrupted++; - - /* ToDo: signal error -> LL */ -} -EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); - -/** - * gigaset_isdn_icall() - signal incoming call - * @at_state: connection state structure. - * - * Called by main module at tasklet level to notify the LL that an incoming - * call has been received. @at_state contains the parameters of the call. - * - * Return value: call disposition (ICALL_*) - */ -int gigaset_isdn_icall(struct at_state_t *at_state) -{ - struct cardstate *cs = at_state->cs; - struct bc_state *bcs = at_state->bcs; - struct gigaset_capi_ctr *iif = cs->iif; - struct gigaset_capi_appl *ap; - u32 actCIPmask; - struct sk_buff *skb; - unsigned int msgsize; - unsigned long flags; - int i; - - /* - * ToDo: signal calls without a free B channel, too - * (requires a u8 handle for the at_state structure that can - * be stored in the PLCI and used in the CONNECT_RESP message - * handler to retrieve it) - */ - if (!bcs) - return ICALL_IGNORE; - - /* prepare CONNECT_IND message, using B channel number as PLCI */ - capi_cmsg_header(&iif->hcmsg, 0, CAPI_CONNECT, CAPI_IND, 0, - iif->ctr.cnr | ((bcs->channel + 1) << 8)); - - /* minimum size, all structs empty */ - msgsize = CAPI_CONNECT_IND_BASELEN; - - /* Bearer Capability (mandatory) */ - if (at_state->str_var[STR_ZBC]) { - /* pass on BC from Gigaset */ - if (encode_ie(at_state->str_var[STR_ZBC], iif->bc_buf, - MAX_BC_OCTETS) < 0) { - dev_warn(cs->dev, "RING ignored - bad BC %s\n", - at_state->str_var[STR_ZBC]); - return ICALL_IGNORE; - } - - /* look up corresponding CIP value */ - iif->hcmsg.CIPValue = 0; /* default if nothing found */ - for (i = 0; i < ARRAY_SIZE(cip2bchlc); i++) - if (cip2bchlc[i].bc != NULL && - cip2bchlc[i].hlc == NULL && - !strcmp(cip2bchlc[i].bc, - at_state->str_var[STR_ZBC])) { - iif->hcmsg.CIPValue = i; - break; - } - } else { - /* no BC (internal call): assume CIP 1 (speech, A-law) */ - iif->hcmsg.CIPValue = 1; - encode_ie(cip2bchlc[1].bc, iif->bc_buf, MAX_BC_OCTETS); - } - iif->hcmsg.BC = iif->bc_buf; - msgsize += iif->hcmsg.BC[0]; - - /* High Layer Compatibility (optional) */ - if (at_state->str_var[STR_ZHLC]) { - /* pass on HLC from Gigaset */ - if (encode_ie(at_state->str_var[STR_ZHLC], iif->hlc_buf, - MAX_HLC_OCTETS) < 0) { - dev_warn(cs->dev, "RING ignored - bad HLC %s\n", - at_state->str_var[STR_ZHLC]); - return ICALL_IGNORE; - } - iif->hcmsg.HLC = iif->hlc_buf; - msgsize += iif->hcmsg.HLC[0]; - - /* look up corresponding CIP value */ - /* keep BC based CIP value if none found */ - if (at_state->str_var[STR_ZBC]) - for (i = 0; i < ARRAY_SIZE(cip2bchlc); i++) - if (cip2bchlc[i].hlc != NULL && - !strcmp(cip2bchlc[i].hlc, - at_state->str_var[STR_ZHLC]) && - !strcmp(cip2bchlc[i].bc, - at_state->str_var[STR_ZBC])) { - iif->hcmsg.CIPValue = i; - break; - } - } - - /* Called Party Number (optional) */ - if (at_state->str_var[STR_ZCPN]) { - i = strlen(at_state->str_var[STR_ZCPN]); - if (i > MAX_NUMBER_DIGITS) { - dev_warn(cs->dev, "RING ignored - bad number %s\n", - at_state->str_var[STR_ZBC]); - return ICALL_IGNORE; - } - iif->cdpty_buf[0] = i + 1; - iif->cdpty_buf[1] = 0x80; /* type / numbering plan unknown */ - memcpy(iif->cdpty_buf + 2, at_state->str_var[STR_ZCPN], i); - iif->hcmsg.CalledPartyNumber = iif->cdpty_buf; - msgsize += iif->hcmsg.CalledPartyNumber[0]; - } - - /* Calling Party Number (optional) */ - if (at_state->str_var[STR_NMBR]) { - i = strlen(at_state->str_var[STR_NMBR]); - if (i > MAX_NUMBER_DIGITS) { - dev_warn(cs->dev, "RING ignored - bad number %s\n", - at_state->str_var[STR_ZBC]); - return ICALL_IGNORE; - } - iif->cgpty_buf[0] = i + 2; - iif->cgpty_buf[1] = 0x00; /* type / numbering plan unknown */ - iif->cgpty_buf[2] = 0x80; /* pres. allowed, not screened */ - memcpy(iif->cgpty_buf + 3, at_state->str_var[STR_NMBR], i); - iif->hcmsg.CallingPartyNumber = iif->cgpty_buf; - msgsize += iif->hcmsg.CallingPartyNumber[0]; - } - - /* remaining parameters (not supported, always left NULL): - * - CalledPartySubaddress - * - CallingPartySubaddress - * - AdditionalInfo - * - BChannelinformation - * - Keypadfacility - * - Useruserdata - * - Facilitydataarray - */ - - gig_dbg(DEBUG_CMD, "icall: PLCI %x CIP %d BC %s", - iif->hcmsg.adr.adrPLCI, iif->hcmsg.CIPValue, - format_ie(iif->hcmsg.BC)); - gig_dbg(DEBUG_CMD, "icall: HLC %s", - format_ie(iif->hcmsg.HLC)); - gig_dbg(DEBUG_CMD, "icall: CgPty %s", - format_ie(iif->hcmsg.CallingPartyNumber)); - gig_dbg(DEBUG_CMD, "icall: CdPty %s", - format_ie(iif->hcmsg.CalledPartyNumber)); - - /* scan application list for matching listeners */ - spin_lock_irqsave(&bcs->aplock, flags); - if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) { - dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n", - __func__, bcs->ap, bcs->apconnstate); - bcs->ap = NULL; - bcs->apconnstate = APCONN_NONE; - } - spin_unlock_irqrestore(&bcs->aplock, flags); - actCIPmask = 1 | (1 << iif->hcmsg.CIPValue); - list_for_each_entry(ap, &iif->appls, ctrlist) - if (actCIPmask & ap->listenCIPmask) { - /* build CONNECT_IND message for this application */ - iif->hcmsg.ApplId = ap->id; - iif->hcmsg.Messagenumber = ap->nextMessageNumber++; - - skb = alloc_skb(msgsize, GFP_ATOMIC); - if (!skb) { - dev_err(cs->dev, "%s: out of memory\n", - __func__); - break; - } - if (capi_cmsg2message(&iif->hcmsg, - __skb_put(skb, msgsize))) { - dev_err(cs->dev, "%s: message parser failure\n", - __func__); - dev_kfree_skb_any(skb); - break; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); - - /* add to listeners on this B channel, update state */ - spin_lock_irqsave(&bcs->aplock, flags); - ap->bcnext = bcs->ap; - bcs->ap = ap; - bcs->chstate |= CHS_NOTIFY_LL; - bcs->apconnstate = APCONN_SETUP; - spin_unlock_irqrestore(&bcs->aplock, flags); - - /* emit message */ - capi_ctr_handle_message(&iif->ctr, ap->id, skb); - } - - /* - * Return "accept" if any listeners. - * Gigaset will send ALERTING. - * There doesn't seem to be a way to avoid this. - */ - return bcs->ap ? ICALL_ACCEPT : ICALL_IGNORE; -} - -/* - * send a DISCONNECT_IND message to an application - * does not sleep, clobbers the controller's hcmsg structure - */ -static void send_disconnect_ind(struct bc_state *bcs, - struct gigaset_capi_appl *ap, u16 reason) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_ctr *iif = cs->iif; - struct sk_buff *skb; - - if (bcs->apconnstate == APCONN_NONE) - return; - - capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND, - ap->nextMessageNumber++, - iif->ctr.cnr | ((bcs->channel + 1) << 8)); - iif->hcmsg.Reason = reason; - skb = alloc_skb(CAPI_DISCONNECT_IND_LEN, GFP_ATOMIC); - if (!skb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - if (capi_cmsg2message(&iif->hcmsg, - __skb_put(skb, CAPI_DISCONNECT_IND_LEN))) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} - -/* - * send a DISCONNECT_B3_IND message to an application - * Parameters: NCCI = 1, NCPI empty, Reason_B3 = 0 - * does not sleep, clobbers the controller's hcmsg structure - */ -static void send_disconnect_b3_ind(struct bc_state *bcs, - struct gigaset_capi_appl *ap) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_ctr *iif = cs->iif; - struct sk_buff *skb; - - /* nothing to do if no logical connection active */ - if (bcs->apconnstate < APCONN_ACTIVE) - return; - bcs->apconnstate = APCONN_SETUP; - - capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, - ap->nextMessageNumber++, - iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); - skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_ATOMIC); - if (!skb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - if (capi_cmsg2message(&iif->hcmsg, - __skb_put(skb, CAPI_DISCONNECT_B3_IND_BASELEN))) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} - -/** - * gigaset_isdn_connD() - signal D channel connect - * @bcs: B channel descriptor structure. - * - * Called by main module at tasklet level to notify the LL that the D channel - * connection has been established. - */ -void gigaset_isdn_connD(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_ctr *iif = cs->iif; - struct gigaset_capi_appl *ap; - struct sk_buff *skb; - unsigned int msgsize; - unsigned long flags; - - spin_lock_irqsave(&bcs->aplock, flags); - ap = bcs->ap; - if (!ap) { - spin_unlock_irqrestore(&bcs->aplock, flags); - gig_dbg(DEBUG_CMD, "%s: application gone", __func__); - return; - } - if (bcs->apconnstate == APCONN_NONE) { - spin_unlock_irqrestore(&bcs->aplock, flags); - dev_warn(cs->dev, "%s: application %u not connected\n", - __func__, ap->id); - return; - } - spin_unlock_irqrestore(&bcs->aplock, flags); - while (ap->bcnext) { - /* this should never happen */ - dev_warn(cs->dev, "%s: dropping extra application %u\n", - __func__, ap->bcnext->id); - send_disconnect_ind(bcs, ap->bcnext, - CapiCallGivenToOtherApplication); - ap->bcnext = ap->bcnext->bcnext; - } - - /* prepare CONNECT_ACTIVE_IND message - * Note: LLC not supported by device - */ - capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_CONNECT_ACTIVE, CAPI_IND, - ap->nextMessageNumber++, - iif->ctr.cnr | ((bcs->channel + 1) << 8)); - - /* minimum size, all structs empty */ - msgsize = CAPI_CONNECT_ACTIVE_IND_BASELEN; - - /* ToDo: set parameter: Connected number - * (requires ev-layer state machine extension to collect - * ZCON device reply) - */ - - /* build and emit CONNECT_ACTIVE_IND message */ - skb = alloc_skb(msgsize, GFP_ATOMIC); - if (!skb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - if (capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize))) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} - -/** - * gigaset_isdn_hupD() - signal D channel hangup - * @bcs: B channel descriptor structure. - * - * Called by main module at tasklet level to notify the LL that the D channel - * connection has been shut down. - */ -void gigaset_isdn_hupD(struct bc_state *bcs) -{ - struct gigaset_capi_appl *ap; - unsigned long flags; - - /* - * ToDo: pass on reason code reported by device - * (requires ev-layer state machine extension to collect - * ZCAU device reply) - */ - spin_lock_irqsave(&bcs->aplock, flags); - while (bcs->ap != NULL) { - ap = bcs->ap; - bcs->ap = ap->bcnext; - spin_unlock_irqrestore(&bcs->aplock, flags); - send_disconnect_b3_ind(bcs, ap); - send_disconnect_ind(bcs, ap, 0); - spin_lock_irqsave(&bcs->aplock, flags); - } - bcs->apconnstate = APCONN_NONE; - spin_unlock_irqrestore(&bcs->aplock, flags); -} - -/** - * gigaset_isdn_connB() - signal B channel connect - * @bcs: B channel descriptor structure. - * - * Called by main module at tasklet level to notify the LL that the B channel - * connection has been established. - */ -void gigaset_isdn_connB(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_ctr *iif = cs->iif; - struct gigaset_capi_appl *ap; - struct sk_buff *skb; - unsigned long flags; - unsigned int msgsize; - u8 command; - - spin_lock_irqsave(&bcs->aplock, flags); - ap = bcs->ap; - if (!ap) { - spin_unlock_irqrestore(&bcs->aplock, flags); - gig_dbg(DEBUG_CMD, "%s: application gone", __func__); - return; - } - if (!bcs->apconnstate) { - spin_unlock_irqrestore(&bcs->aplock, flags); - dev_warn(cs->dev, "%s: application %u not connected\n", - __func__, ap->id); - return; - } - - /* - * emit CONNECT_B3_ACTIVE_IND if we already got CONNECT_B3_REQ; - * otherwise we have to emit CONNECT_B3_IND first, and follow up with - * CONNECT_B3_ACTIVE_IND in reply to CONNECT_B3_RESP - * Parameters in both cases always: NCCI = 1, NCPI empty - */ - if (bcs->apconnstate >= APCONN_ACTIVE) { - command = CAPI_CONNECT_B3_ACTIVE; - msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; - } else { - command = CAPI_CONNECT_B3; - msgsize = CAPI_CONNECT_B3_IND_BASELEN; - } - bcs->apconnstate = APCONN_ACTIVE; - - spin_unlock_irqrestore(&bcs->aplock, flags); - - while (ap->bcnext) { - /* this should never happen */ - dev_warn(cs->dev, "%s: dropping extra application %u\n", - __func__, ap->bcnext->id); - send_disconnect_ind(bcs, ap->bcnext, - CapiCallGivenToOtherApplication); - ap->bcnext = ap->bcnext->bcnext; - } - - capi_cmsg_header(&iif->hcmsg, ap->id, command, CAPI_IND, - ap->nextMessageNumber++, - iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); - skb = alloc_skb(msgsize, GFP_ATOMIC); - if (!skb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - if (capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize))) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} - -/** - * gigaset_isdn_hupB() - signal B channel hangup - * @bcs: B channel descriptor structure. - * - * Called by main module to notify the LL that the B channel connection has - * been shut down. - */ -void gigaset_isdn_hupB(struct bc_state *bcs) -{ - struct gigaset_capi_appl *ap = bcs->ap; - - /* ToDo: assure order of DISCONNECT_B3_IND and DISCONNECT_IND ? */ - - if (!ap) { - gig_dbg(DEBUG_CMD, "%s: application gone", __func__); - return; - } - - send_disconnect_b3_ind(bcs, ap); -} - -/** - * gigaset_isdn_start() - signal device availability - * @cs: device descriptor structure. - * - * Called by main module to notify the LL that the device is available for - * use. - */ -void gigaset_isdn_start(struct cardstate *cs) -{ - struct gigaset_capi_ctr *iif = cs->iif; - - /* fill profile data: manufacturer name */ - strcpy(iif->ctr.manu, "Siemens"); - /* CAPI and device version */ - iif->ctr.version.majorversion = 2; /* CAPI 2.0 */ - iif->ctr.version.minorversion = 0; - /* ToDo: check/assert cs->gotfwver? */ - iif->ctr.version.majormanuversion = cs->fwver[0]; - iif->ctr.version.minormanuversion = cs->fwver[1]; - /* number of B channels supported */ - iif->ctr.profile.nbchannel = cs->channels; - /* global options: internal controller, supplementary services */ - iif->ctr.profile.goptions = 0x11; - /* B1 protocols: 64 kbit/s HDLC or transparent */ - iif->ctr.profile.support1 = 0x03; - /* B2 protocols: transparent only */ - /* ToDo: X.75 SLP ? */ - iif->ctr.profile.support2 = 0x02; - /* B3 protocols: transparent only */ - iif->ctr.profile.support3 = 0x01; - /* no serial number */ - strcpy(iif->ctr.serial, "0"); - capi_ctr_ready(&iif->ctr); -} - -/** - * gigaset_isdn_stop() - signal device unavailability - * @cs: device descriptor structure. - * - * Called by main module to notify the LL that the device is no longer - * available for use. - */ -void gigaset_isdn_stop(struct cardstate *cs) -{ - struct gigaset_capi_ctr *iif = cs->iif; - capi_ctr_down(&iif->ctr); -} - -/* - * kernel CAPI callback methods - * ============================ - */ - -/* - * register CAPI application - */ -static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl, - capi_register_params *rp) -{ - struct gigaset_capi_ctr *iif - = container_of(ctr, struct gigaset_capi_ctr, ctr); - struct cardstate *cs = ctr->driverdata; - struct gigaset_capi_appl *ap; - - gig_dbg(DEBUG_CMD, "%s [%u] l3cnt=%u blkcnt=%u blklen=%u", - __func__, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen); - - list_for_each_entry(ap, &iif->appls, ctrlist) - if (ap->id == appl) { - dev_notice(cs->dev, - "application %u already registered\n", appl); - return; - } - - ap = kzalloc(sizeof(*ap), GFP_KERNEL); - if (!ap) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - ap->id = appl; - ap->rp = *rp; - - list_add(&ap->ctrlist, &iif->appls); - dev_info(cs->dev, "application %u registered\n", ap->id); -} - -/* - * remove CAPI application from channel - * helper function to keep indentation levels down and stay in 80 columns - */ - -static inline void remove_appl_from_channel(struct bc_state *bcs, - struct gigaset_capi_appl *ap) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_appl *bcap; - unsigned long flags; - int prevconnstate; - - spin_lock_irqsave(&bcs->aplock, flags); - bcap = bcs->ap; - if (bcap == NULL) { - spin_unlock_irqrestore(&bcs->aplock, flags); - return; - } - - /* check first application on channel */ - if (bcap == ap) { - bcs->ap = ap->bcnext; - if (bcs->ap != NULL) { - spin_unlock_irqrestore(&bcs->aplock, flags); - return; - } - - /* none left, clear channel state */ - prevconnstate = bcs->apconnstate; - bcs->apconnstate = APCONN_NONE; - spin_unlock_irqrestore(&bcs->aplock, flags); - - if (prevconnstate == APCONN_ACTIVE) { - dev_notice(cs->dev, "%s: hanging up channel %u\n", - __func__, bcs->channel); - gigaset_add_event(cs, &bcs->at_state, - EV_HUP, NULL, 0, NULL); - gigaset_schedule_event(cs); - } - return; - } - - /* check remaining list */ - do { - if (bcap->bcnext == ap) { - bcap->bcnext = bcap->bcnext->bcnext; - spin_unlock_irqrestore(&bcs->aplock, flags); - return; - } - bcap = bcap->bcnext; - } while (bcap != NULL); - spin_unlock_irqrestore(&bcs->aplock, flags); -} - -/* - * release CAPI application - */ -static void gigaset_release_appl(struct capi_ctr *ctr, u16 appl) -{ - struct gigaset_capi_ctr *iif - = container_of(ctr, struct gigaset_capi_ctr, ctr); - struct cardstate *cs = iif->ctr.driverdata; - struct gigaset_capi_appl *ap, *tmp; - unsigned ch; - - gig_dbg(DEBUG_CMD, "%s [%u]", __func__, appl); - - list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist) - if (ap->id == appl) { - /* remove from any channels */ - for (ch = 0; ch < cs->channels; ch++) - remove_appl_from_channel(&cs->bcs[ch], ap); - - /* remove from registration list */ - list_del(&ap->ctrlist); - kfree(ap); - dev_info(cs->dev, "application %u released\n", appl); - } -} - -/* - * ===================================================================== - * outgoing CAPI message handler - * ===================================================================== - */ - -/* - * helper function: emit reply message with given Info value - */ -static void send_conf(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb, - u16 info) -{ - struct cardstate *cs = iif->ctr.driverdata; - - /* - * _CONF replies always only have NCCI and Info parameters - * so they'll fit into the _REQ message skb - */ - capi_cmsg_answer(&iif->acmsg); - iif->acmsg.Info = info; - if (capi_cmsg2message(&iif->acmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - __skb_trim(skb, CAPI_STDCONF_LEN); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} - -/* - * process FACILITY_REQ message - */ -static void do_facility_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct sk_buff *cskb; - u8 *pparam; - unsigned int msgsize = CAPI_FACILITY_CONF_BASELEN; - u16 function, info; - static u8 confparam[10]; /* max. 9 octets + length byte */ - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - - /* - * Facility Request Parameter is not decoded by capi_message2cmsg() - * encoding depends on Facility Selector - */ - switch (cmsg->FacilitySelector) { - case CAPI_FACILITY_DTMF: /* ToDo */ - info = CapiFacilityNotSupported; - confparam[0] = 2; /* length */ - /* DTMF information: Unknown DTMF request */ - capimsg_setu16(confparam, 1, 2); - break; - - case CAPI_FACILITY_V42BIS: /* not supported */ - info = CapiFacilityNotSupported; - confparam[0] = 2; /* length */ - /* V.42 bis information: not available */ - capimsg_setu16(confparam, 1, 1); - break; - - case CAPI_FACILITY_SUPPSVC: - /* decode Function parameter */ - pparam = cmsg->FacilityRequestParameter; - if (pparam == NULL || pparam[0] < 2) { - dev_notice(cs->dev, "%s: %s missing\n", "FACILITY_REQ", - "Facility Request Parameter"); - send_conf(iif, ap, skb, CapiIllMessageParmCoding); - return; - } - function = CAPIMSG_U16(pparam, 1); - switch (function) { - case CAPI_SUPPSVC_GETSUPPORTED: - info = CapiSuccess; - /* Supplementary Service specific parameter */ - confparam[3] = 6; /* length */ - /* Supplementary services info: Success */ - capimsg_setu16(confparam, 4, CapiSuccess); - /* Supported Services: none */ - capimsg_setu32(confparam, 6, 0); - break; - case CAPI_SUPPSVC_LISTEN: - if (pparam[0] < 7 || pparam[3] < 4) { - dev_notice(cs->dev, "%s: %s missing\n", - "FACILITY_REQ", "Notification Mask"); - send_conf(iif, ap, skb, - CapiIllMessageParmCoding); - return; - } - if (CAPIMSG_U32(pparam, 4) != 0) { - dev_notice(cs->dev, - "%s: unsupported supplementary service notification mask 0x%x\n", - "FACILITY_REQ", CAPIMSG_U32(pparam, 4)); - info = CapiFacilitySpecificFunctionNotSupported; - confparam[3] = 2; /* length */ - capimsg_setu16(confparam, 4, - CapiSupplementaryServiceNotSupported); - break; - } - info = CapiSuccess; - confparam[3] = 2; /* length */ - capimsg_setu16(confparam, 4, CapiSuccess); - break; - - /* ToDo: add supported services */ - - default: - dev_notice(cs->dev, - "%s: unsupported supplementary service function 0x%04x\n", - "FACILITY_REQ", function); - info = CapiFacilitySpecificFunctionNotSupported; - /* Supplementary Service specific parameter */ - confparam[3] = 2; /* length */ - /* Supplementary services info: not supported */ - capimsg_setu16(confparam, 4, - CapiSupplementaryServiceNotSupported); - } - - /* Facility confirmation parameter */ - confparam[0] = confparam[3] + 3; /* total length */ - /* Function: copy from _REQ message */ - capimsg_setu16(confparam, 1, function); - /* Supplementary Service specific parameter already set above */ - break; - - case CAPI_FACILITY_WAKEUP: /* ToDo */ - info = CapiFacilityNotSupported; - confparam[0] = 2; /* length */ - /* Number of accepted awake request parameters: 0 */ - capimsg_setu16(confparam, 1, 0); - break; - - default: - info = CapiFacilityNotSupported; - confparam[0] = 0; /* empty struct */ - } - - /* send FACILITY_CONF with given Info and confirmation parameter */ - dev_kfree_skb_any(skb); - capi_cmsg_answer(cmsg); - cmsg->Info = info; - cmsg->FacilityConfirmationParameter = confparam; - msgsize += confparam[0]; /* length */ - cskb = alloc_skb(msgsize, GFP_ATOMIC); - if (!cskb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - if (capi_cmsg2message(cmsg, __skb_put(cskb, msgsize))) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(cskb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, cskb); -} - - -/* - * process LISTEN_REQ message - * just store the masks in the application data structure - */ -static void do_listen_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - - /* decode message */ - if (capi_message2cmsg(&iif->acmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - - /* store listening parameters */ - ap->listenInfoMask = iif->acmsg.InfoMask; - ap->listenCIPmask = iif->acmsg.CIPmask; - send_conf(iif, ap, skb, CapiSuccess); -} - -/* - * process ALERT_REQ message - * nothing to do, Gigaset always alerts anyway - */ -static void do_alert_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - - /* decode message */ - if (capi_message2cmsg(&iif->acmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - send_conf(iif, ap, skb, CapiAlertAlreadySent); -} - -/* - * process CONNECT_REQ message - * allocate a B channel, prepare dial commands, queue a DIAL event, - * emit CONNECT_CONF reply - */ -static void do_connect_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct bc_state *bcs; - char **commands; - char *s; - u8 *pp; - unsigned long flags; - int i, l, lbc, lhlc; - u16 info; - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - - /* get free B channel & construct PLCI */ - bcs = gigaset_get_free_channel(cs); - if (!bcs) { - dev_notice(cs->dev, "%s: no B channel available\n", - "CONNECT_REQ"); - send_conf(iif, ap, skb, CapiNoPlciAvailable); - return; - } - spin_lock_irqsave(&bcs->aplock, flags); - if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) - dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n", - __func__, bcs->ap, bcs->apconnstate); - ap->bcnext = NULL; - bcs->ap = ap; - bcs->apconnstate = APCONN_SETUP; - spin_unlock_irqrestore(&bcs->aplock, flags); - - bcs->rx_bufsize = ap->rp.datablklen; - dev_kfree_skb(bcs->rx_skb); - gigaset_new_rx_skb(bcs); - cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8; - - /* build command table */ - commands = kcalloc(AT_NUM, sizeof(*commands), GFP_KERNEL); - if (!commands) - goto oom; - - /* encode parameter: Called party number */ - pp = cmsg->CalledPartyNumber; - if (pp == NULL || *pp == 0) { - dev_notice(cs->dev, "%s: %s missing\n", - "CONNECT_REQ", "Called party number"); - info = CapiIllMessageParmCoding; - goto error; - } - l = *pp++; - /* check type of number/numbering plan byte */ - switch (*pp) { - case 0x80: /* unknown type / unknown numbering plan */ - case 0x81: /* unknown type / ISDN/Telephony numbering plan */ - break; - default: /* others: warn about potential misinterpretation */ - dev_notice(cs->dev, "%s: %s type/plan 0x%02x unsupported\n", - "CONNECT_REQ", "Called party number", *pp); - } - pp++; - l--; - /* translate "**" internal call prefix to CTP value */ - if (l >= 2 && pp[0] == '*' && pp[1] == '*') { - s = "^SCTP=0\r"; - pp += 2; - l -= 2; - } else { - s = "^SCTP=1\r"; - } - commands[AT_TYPE] = kstrdup(s, GFP_KERNEL); - if (!commands[AT_TYPE]) - goto oom; - commands[AT_DIAL] = kmalloc(l + 3, GFP_KERNEL); - if (!commands[AT_DIAL]) - goto oom; - snprintf(commands[AT_DIAL], l + 3, "D%.*s\r", l, pp); - - /* encode parameter: Calling party number */ - pp = cmsg->CallingPartyNumber; - if (pp != NULL && *pp > 0) { - l = *pp++; - - /* check type of number/numbering plan byte */ - /* ToDo: allow for/handle Ext=1? */ - switch (*pp) { - case 0x00: /* unknown type / unknown numbering plan */ - case 0x01: /* unknown type / ISDN/Telephony num. plan */ - break; - default: - dev_notice(cs->dev, - "%s: %s type/plan 0x%02x unsupported\n", - "CONNECT_REQ", "Calling party number", *pp); - } - pp++; - l--; - - /* check presentation indicator */ - if (!l) { - dev_notice(cs->dev, "%s: %s IE truncated\n", - "CONNECT_REQ", "Calling party number"); - info = CapiIllMessageParmCoding; - goto error; - } - switch (*pp & 0xfc) { /* ignore Screening indicator */ - case 0x80: /* Presentation allowed */ - s = "^SCLIP=1\r"; - break; - case 0xa0: /* Presentation restricted */ - s = "^SCLIP=0\r"; - break; - default: - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "CONNECT_REQ", - "Presentation/Screening indicator", - *pp); - s = "^SCLIP=1\r"; - } - commands[AT_CLIP] = kstrdup(s, GFP_KERNEL); - if (!commands[AT_CLIP]) - goto oom; - pp++; - l--; - - if (l) { - /* number */ - commands[AT_MSN] = kmalloc(l + 8, GFP_KERNEL); - if (!commands[AT_MSN]) - goto oom; - snprintf(commands[AT_MSN], l + 8, "^SMSN=%*s\r", l, pp); - } - } - - /* check parameter: CIP Value */ - if (cmsg->CIPValue >= ARRAY_SIZE(cip2bchlc) || - (cmsg->CIPValue > 0 && cip2bchlc[cmsg->CIPValue].bc == NULL)) { - dev_notice(cs->dev, "%s: unknown CIP value %d\n", - "CONNECT_REQ", cmsg->CIPValue); - info = CapiCipValueUnknown; - goto error; - } - - /* - * check/encode parameters: BC & HLC - * must be encoded together as device doesn't accept HLC separately - * explicit parameters override values derived from CIP - */ - - /* determine lengths */ - if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */ - lbc = 2 * cmsg->BC[0]; - else if (cip2bchlc[cmsg->CIPValue].bc) /* BC derived from CIP */ - lbc = strlen(cip2bchlc[cmsg->CIPValue].bc); - else /* no BC */ - lbc = 0; - if (cmsg->HLC && cmsg->HLC[0]) /* HLC specified explicitly */ - lhlc = 2 * cmsg->HLC[0]; - else if (cip2bchlc[cmsg->CIPValue].hlc) /* HLC derived from CIP */ - lhlc = strlen(cip2bchlc[cmsg->CIPValue].hlc); - else /* no HLC */ - lhlc = 0; - - if (lbc) { - /* have BC: allocate and assemble command string */ - l = lbc + 7; /* "^SBC=" + value + "\r" + null byte */ - if (lhlc) - l += lhlc + 7; /* ";^SHLC=" + value */ - commands[AT_BC] = kmalloc(l, GFP_KERNEL); - if (!commands[AT_BC]) - goto oom; - strcpy(commands[AT_BC], "^SBC="); - if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */ - decode_ie(cmsg->BC, commands[AT_BC] + 5); - else /* BC derived from CIP */ - strcpy(commands[AT_BC] + 5, - cip2bchlc[cmsg->CIPValue].bc); - if (lhlc) { - strcpy(commands[AT_BC] + lbc + 5, ";^SHLC="); - if (cmsg->HLC && cmsg->HLC[0]) - /* HLC specified explicitly */ - decode_ie(cmsg->HLC, - commands[AT_BC] + lbc + 12); - else /* HLC derived from CIP */ - strcpy(commands[AT_BC] + lbc + 12, - cip2bchlc[cmsg->CIPValue].hlc); - } - strcpy(commands[AT_BC] + l - 2, "\r"); - } else { - /* no BC */ - if (lhlc) { - dev_notice(cs->dev, "%s: cannot set HLC without BC\n", - "CONNECT_REQ"); - info = CapiIllMessageParmCoding; /* ? */ - goto error; - } - } - - /* check/encode parameter: B Protocol */ - if (cmsg->BProtocol == CAPI_DEFAULT) { - bcs->proto2 = L2_HDLC; - dev_warn(cs->dev, - "B2 Protocol X.75 SLP unsupported, using Transparent\n"); - } else { - switch (cmsg->B1protocol) { - case 0: - bcs->proto2 = L2_HDLC; - break; - case 1: - bcs->proto2 = L2_VOICE; - break; - default: - dev_warn(cs->dev, - "B1 Protocol %u unsupported, using Transparent\n", - cmsg->B1protocol); - bcs->proto2 = L2_VOICE; - } - if (cmsg->B2protocol != 1) - dev_warn(cs->dev, - "B2 Protocol %u unsupported, using Transparent\n", - cmsg->B2protocol); - if (cmsg->B3protocol != 0) - dev_warn(cs->dev, - "B3 Protocol %u unsupported, using Transparent\n", - cmsg->B3protocol); - ignore_cstruct_param(cs, cmsg->B1configuration, - "CONNECT_REQ", "B1 Configuration"); - ignore_cstruct_param(cs, cmsg->B2configuration, - "CONNECT_REQ", "B2 Configuration"); - ignore_cstruct_param(cs, cmsg->B3configuration, - "CONNECT_REQ", "B3 Configuration"); - } - commands[AT_PROTO] = kmalloc(9, GFP_KERNEL); - if (!commands[AT_PROTO]) - goto oom; - snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); - - /* ToDo: check/encode remaining parameters */ - ignore_cstruct_param(cs, cmsg->CalledPartySubaddress, - "CONNECT_REQ", "Called pty subaddr"); - ignore_cstruct_param(cs, cmsg->CallingPartySubaddress, - "CONNECT_REQ", "Calling pty subaddr"); - ignore_cstruct_param(cs, cmsg->LLC, - "CONNECT_REQ", "LLC"); - if (cmsg->AdditionalInfo != CAPI_DEFAULT) { - ignore_cstruct_param(cs, cmsg->BChannelinformation, - "CONNECT_REQ", "B Channel Information"); - ignore_cstruct_param(cs, cmsg->Keypadfacility, - "CONNECT_REQ", "Keypad Facility"); - ignore_cstruct_param(cs, cmsg->Useruserdata, - "CONNECT_REQ", "User-User Data"); - ignore_cstruct_param(cs, cmsg->Facilitydataarray, - "CONNECT_REQ", "Facility Data Array"); - } - - /* encode parameter: B channel to use */ - commands[AT_ISO] = kmalloc(9, GFP_KERNEL); - if (!commands[AT_ISO]) - goto oom; - snprintf(commands[AT_ISO], 9, "^SISO=%u\r", - (unsigned) bcs->channel + 1); - - /* queue & schedule EV_DIAL event */ - if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands, - bcs->at_state.seq_index, NULL)) { - info = CAPI_MSGOSRESOURCEERR; - goto error; - } - gigaset_schedule_event(cs); - send_conf(iif, ap, skb, CapiSuccess); - return; - -oom: - dev_err(cs->dev, "%s: out of memory\n", __func__); - info = CAPI_MSGOSRESOURCEERR; -error: - if (commands) - for (i = 0; i < AT_NUM; i++) - kfree(commands[i]); - kfree(commands); - gigaset_free_channel(bcs); - send_conf(iif, ap, skb, info); -} - -/* - * process CONNECT_RESP message - * checks protocol parameters and queues an ACCEPT or HUP event - */ -static void do_connect_resp(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct bc_state *bcs; - struct gigaset_capi_appl *oap; - unsigned long flags; - int channel; - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - dev_kfree_skb_any(skb); - - /* extract and check channel number from PLCI */ - channel = (cmsg->adr.adrPLCI >> 8) & 0xff; - if (!channel || channel > cs->channels) { - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "CONNECT_RESP", "PLCI", cmsg->adr.adrPLCI); - return; - } - bcs = cs->bcs + channel - 1; - - switch (cmsg->Reject) { - case 0: /* Accept */ - /* drop all competing applications, keep only this one */ - spin_lock_irqsave(&bcs->aplock, flags); - while (bcs->ap != NULL) { - oap = bcs->ap; - bcs->ap = oap->bcnext; - if (oap != ap) { - spin_unlock_irqrestore(&bcs->aplock, flags); - send_disconnect_ind(bcs, oap, - CapiCallGivenToOtherApplication); - spin_lock_irqsave(&bcs->aplock, flags); - } - } - ap->bcnext = NULL; - bcs->ap = ap; - spin_unlock_irqrestore(&bcs->aplock, flags); - - bcs->rx_bufsize = ap->rp.datablklen; - dev_kfree_skb(bcs->rx_skb); - gigaset_new_rx_skb(bcs); - bcs->chstate |= CHS_NOTIFY_LL; - - /* check/encode B channel protocol */ - if (cmsg->BProtocol == CAPI_DEFAULT) { - bcs->proto2 = L2_HDLC; - dev_warn(cs->dev, - "B2 Protocol X.75 SLP unsupported, using Transparent\n"); - } else { - switch (cmsg->B1protocol) { - case 0: - bcs->proto2 = L2_HDLC; - break; - case 1: - bcs->proto2 = L2_VOICE; - break; - default: - dev_warn(cs->dev, - "B1 Protocol %u unsupported, using Transparent\n", - cmsg->B1protocol); - bcs->proto2 = L2_VOICE; - } - if (cmsg->B2protocol != 1) - dev_warn(cs->dev, - "B2 Protocol %u unsupported, using Transparent\n", - cmsg->B2protocol); - if (cmsg->B3protocol != 0) - dev_warn(cs->dev, - "B3 Protocol %u unsupported, using Transparent\n", - cmsg->B3protocol); - ignore_cstruct_param(cs, cmsg->B1configuration, - "CONNECT_RESP", "B1 Configuration"); - ignore_cstruct_param(cs, cmsg->B2configuration, - "CONNECT_RESP", "B2 Configuration"); - ignore_cstruct_param(cs, cmsg->B3configuration, - "CONNECT_RESP", "B3 Configuration"); - } - - /* ToDo: check/encode remaining parameters */ - ignore_cstruct_param(cs, cmsg->ConnectedNumber, - "CONNECT_RESP", "Connected Number"); - ignore_cstruct_param(cs, cmsg->ConnectedSubaddress, - "CONNECT_RESP", "Connected Subaddress"); - ignore_cstruct_param(cs, cmsg->LLC, - "CONNECT_RESP", "LLC"); - if (cmsg->AdditionalInfo != CAPI_DEFAULT) { - ignore_cstruct_param(cs, cmsg->BChannelinformation, - "CONNECT_RESP", "BChannel Information"); - ignore_cstruct_param(cs, cmsg->Keypadfacility, - "CONNECT_RESP", "Keypad Facility"); - ignore_cstruct_param(cs, cmsg->Useruserdata, - "CONNECT_RESP", "User-User Data"); - ignore_cstruct_param(cs, cmsg->Facilitydataarray, - "CONNECT_RESP", "Facility Data Array"); - } - - /* Accept call */ - if (!gigaset_add_event(cs, &cs->bcs[channel - 1].at_state, - EV_ACCEPT, NULL, 0, NULL)) - return; - gigaset_schedule_event(cs); - return; - - case 1: /* Ignore */ - /* send DISCONNECT_IND to this application */ - send_disconnect_ind(bcs, ap, 0); - - /* remove it from the list of listening apps */ - spin_lock_irqsave(&bcs->aplock, flags); - if (bcs->ap == ap) { - bcs->ap = ap->bcnext; - if (bcs->ap == NULL) { - /* last one: stop ev-layer hupD notifications */ - bcs->apconnstate = APCONN_NONE; - bcs->chstate &= ~CHS_NOTIFY_LL; - } - spin_unlock_irqrestore(&bcs->aplock, flags); - return; - } - for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) { - if (oap->bcnext == ap) { - oap->bcnext = oap->bcnext->bcnext; - spin_unlock_irqrestore(&bcs->aplock, flags); - return; - } - } - spin_unlock_irqrestore(&bcs->aplock, flags); - dev_err(cs->dev, "%s: application %u not found\n", - __func__, ap->id); - return; - - default: /* Reject */ - /* drop all competing applications, keep only this one */ - spin_lock_irqsave(&bcs->aplock, flags); - while (bcs->ap != NULL) { - oap = bcs->ap; - bcs->ap = oap->bcnext; - if (oap != ap) { - spin_unlock_irqrestore(&bcs->aplock, flags); - send_disconnect_ind(bcs, oap, - CapiCallGivenToOtherApplication); - spin_lock_irqsave(&bcs->aplock, flags); - } - } - ap->bcnext = NULL; - bcs->ap = ap; - spin_unlock_irqrestore(&bcs->aplock, flags); - - /* reject call - will trigger DISCONNECT_IND for this app */ - dev_info(cs->dev, "%s: Reject=%x\n", - "CONNECT_RESP", cmsg->Reject); - if (!gigaset_add_event(cs, &cs->bcs[channel - 1].at_state, - EV_HUP, NULL, 0, NULL)) - return; - gigaset_schedule_event(cs); - return; - } -} - -/* - * process CONNECT_B3_REQ message - * build NCCI and emit CONNECT_B3_CONF reply - */ -static void do_connect_b3_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct bc_state *bcs; - int channel; - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - - /* extract and check channel number from PLCI */ - channel = (cmsg->adr.adrPLCI >> 8) & 0xff; - if (!channel || channel > cs->channels) { - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "CONNECT_B3_REQ", "PLCI", cmsg->adr.adrPLCI); - send_conf(iif, ap, skb, CapiIllContrPlciNcci); - return; - } - bcs = &cs->bcs[channel - 1]; - - /* mark logical connection active */ - bcs->apconnstate = APCONN_ACTIVE; - - /* build NCCI: always 1 (one B3 connection only) */ - cmsg->adr.adrNCCI |= 1 << 16; - - /* NCPI parameter: not applicable for B3 Transparent */ - ignore_cstruct_param(cs, cmsg->NCPI, "CONNECT_B3_REQ", "NCPI"); - send_conf(iif, ap, skb, - (cmsg->NCPI && cmsg->NCPI[0]) ? - CapiNcpiNotSupportedByProtocol : CapiSuccess); -} - -/* - * process CONNECT_B3_RESP message - * Depending on the Reject parameter, either emit CONNECT_B3_ACTIVE_IND - * or queue EV_HUP and emit DISCONNECT_B3_IND. - * The emitted message is always shorter than the received one, - * allowing to reuse the skb. - */ -static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct bc_state *bcs; - int channel; - unsigned int msgsize; - u8 command; - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - - /* extract and check channel number and NCCI */ - channel = (cmsg->adr.adrNCCI >> 8) & 0xff; - if (!channel || channel > cs->channels || - ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) { - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "CONNECT_B3_RESP", "NCCI", cmsg->adr.adrNCCI); - dev_kfree_skb_any(skb); - return; - } - bcs = &cs->bcs[channel - 1]; - - if (cmsg->Reject) { - /* Reject: clear B3 connect received flag */ - bcs->apconnstate = APCONN_SETUP; - - /* trigger hangup, causing eventual DISCONNECT_IND */ - if (!gigaset_add_event(cs, &bcs->at_state, - EV_HUP, NULL, 0, NULL)) { - dev_kfree_skb_any(skb); - return; - } - gigaset_schedule_event(cs); - - /* emit DISCONNECT_B3_IND */ - command = CAPI_DISCONNECT_B3; - msgsize = CAPI_DISCONNECT_B3_IND_BASELEN; - } else { - /* - * Accept: emit CONNECT_B3_ACTIVE_IND immediately, as - * we only send CONNECT_B3_IND if the B channel is up - */ - command = CAPI_CONNECT_B3_ACTIVE; - msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; - } - capi_cmsg_header(cmsg, ap->id, command, CAPI_IND, - ap->nextMessageNumber++, cmsg->adr.adrNCCI); - __skb_trim(skb, msgsize); - if (capi_cmsg2message(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} - -/* - * process DISCONNECT_REQ message - * schedule EV_HUP and emit DISCONNECT_B3_IND if necessary, - * emit DISCONNECT_CONF reply - */ -static void do_disconnect_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct bc_state *bcs; - _cmsg *b3cmsg; - struct sk_buff *b3skb; - int channel; - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - - /* extract and check channel number from PLCI */ - channel = (cmsg->adr.adrPLCI >> 8) & 0xff; - if (!channel || channel > cs->channels) { - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "DISCONNECT_REQ", "PLCI", cmsg->adr.adrPLCI); - send_conf(iif, ap, skb, CapiIllContrPlciNcci); - return; - } - bcs = cs->bcs + channel - 1; - - /* ToDo: process parameter: Additional info */ - if (cmsg->AdditionalInfo != CAPI_DEFAULT) { - ignore_cstruct_param(cs, cmsg->BChannelinformation, - "DISCONNECT_REQ", "B Channel Information"); - ignore_cstruct_param(cs, cmsg->Keypadfacility, - "DISCONNECT_REQ", "Keypad Facility"); - ignore_cstruct_param(cs, cmsg->Useruserdata, - "DISCONNECT_REQ", "User-User Data"); - ignore_cstruct_param(cs, cmsg->Facilitydataarray, - "DISCONNECT_REQ", "Facility Data Array"); - } - - /* skip if DISCONNECT_IND already sent */ - if (!bcs->apconnstate) - return; - - /* check for active logical connection */ - if (bcs->apconnstate >= APCONN_ACTIVE) { - /* clear it */ - bcs->apconnstate = APCONN_SETUP; - - /* - * emit DISCONNECT_B3_IND with cause 0x3301 - * use separate cmsg structure, as the content of iif->acmsg - * is still needed for creating the _CONF message - */ - b3cmsg = kmalloc(sizeof(*b3cmsg), GFP_KERNEL); - if (!b3cmsg) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); - return; - } - capi_cmsg_header(b3cmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, - ap->nextMessageNumber++, - cmsg->adr.adrPLCI | (1 << 16)); - b3cmsg->Reason_B3 = CapiProtocolErrorLayer1; - b3skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_KERNEL); - if (b3skb == NULL) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); - kfree(b3cmsg); - return; - } - if (capi_cmsg2message(b3cmsg, - __skb_put(b3skb, CAPI_DISCONNECT_B3_IND_BASELEN))) { - dev_err(cs->dev, "%s: message parser failure\n", - __func__); - kfree(b3cmsg); - dev_kfree_skb_any(b3skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, b3cmsg); - kfree(b3cmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, b3skb); - } - - /* trigger hangup, causing eventual DISCONNECT_IND */ - if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { - send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); - return; - } - gigaset_schedule_event(cs); - - /* emit reply */ - send_conf(iif, ap, skb, CapiSuccess); -} - -/* - * process DISCONNECT_B3_REQ message - * schedule EV_HUP and emit DISCONNECT_B3_CONF reply - */ -static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct bc_state *bcs; - int channel; - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - - /* extract and check channel number and NCCI */ - channel = (cmsg->adr.adrNCCI >> 8) & 0xff; - if (!channel || channel > cs->channels || - ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) { - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "DISCONNECT_B3_REQ", "NCCI", cmsg->adr.adrNCCI); - send_conf(iif, ap, skb, CapiIllContrPlciNcci); - return; - } - bcs = &cs->bcs[channel - 1]; - - /* reject if logical connection not active */ - if (bcs->apconnstate < APCONN_ACTIVE) { - send_conf(iif, ap, skb, - CapiMessageNotSupportedInCurrentState); - return; - } - - /* trigger hangup, causing eventual DISCONNECT_B3_IND */ - if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { - send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); - return; - } - gigaset_schedule_event(cs); - - /* NCPI parameter: not applicable for B3 Transparent */ - ignore_cstruct_param(cs, cmsg->NCPI, - "DISCONNECT_B3_REQ", "NCPI"); - send_conf(iif, ap, skb, - (cmsg->NCPI && cmsg->NCPI[0]) ? - CapiNcpiNotSupportedByProtocol : CapiSuccess); -} - -/* - * process DATA_B3_REQ message - */ -static void do_data_b3_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - struct bc_state *bcs; - int channel = CAPIMSG_PLCI_PART(skb->data); - u16 ncci = CAPIMSG_NCCI_PART(skb->data); - u16 msglen = CAPIMSG_LEN(skb->data); - u16 datalen = CAPIMSG_DATALEN(skb->data); - u16 flags = CAPIMSG_FLAGS(skb->data); - u16 msgid = CAPIMSG_MSGID(skb->data); - u16 handle = CAPIMSG_HANDLE_REQ(skb->data); - - /* frequent message, avoid _cmsg overhead */ - dump_rawmsg(DEBUG_MCMD, __func__, skb->data); - - /* check parameters */ - if (channel == 0 || channel > cs->channels || ncci != 1) { - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "DATA_B3_REQ", "NCCI", CAPIMSG_NCCI(skb->data)); - send_conf(iif, ap, skb, CapiIllContrPlciNcci); - return; - } - bcs = &cs->bcs[channel - 1]; - if (msglen != CAPI_DATA_B3_REQ_LEN && msglen != CAPI_DATA_B3_REQ_LEN64) - dev_notice(cs->dev, "%s: unexpected length %d\n", - "DATA_B3_REQ", msglen); - if (msglen + datalen != skb->len) - dev_notice(cs->dev, "%s: length mismatch (%d+%d!=%d)\n", - "DATA_B3_REQ", msglen, datalen, skb->len); - if (msglen + datalen > skb->len) { - /* message too short for announced data length */ - send_conf(iif, ap, skb, CapiIllMessageParmCoding); /* ? */ - return; - } - if (flags & CAPI_FLAGS_RESERVED) { - dev_notice(cs->dev, "%s: reserved flags set (%x)\n", - "DATA_B3_REQ", flags); - send_conf(iif, ap, skb, CapiIllMessageParmCoding); - return; - } - - /* reject if logical connection not active */ - if (bcs->apconnstate < APCONN_ACTIVE) { - send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); - return; - } - - /* pull CAPI message into link layer header */ - skb_reset_mac_header(skb); - skb->mac_len = msglen; - skb_pull(skb, msglen); - - /* pass to device-specific module */ - if (cs->ops->send_skb(bcs, skb) < 0) { - send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); - return; - } - - /* - * DATA_B3_CONF will be sent by gigaset_skb_sent() only if "delivery - * confirmation" bit is set; otherwise we have to send it now - */ - if (!(flags & CAPI_FLAGS_DELIVERY_CONFIRMATION)) - send_data_b3_conf(cs, &iif->ctr, ap->id, msgid, channel, handle, - flags ? CapiFlagsNotSupportedByProtocol - : CAPI_NOERROR); -} - -/* - * process RESET_B3_REQ message - * just always reply "not supported by current protocol" - */ -static void do_reset_b3_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - - /* decode message */ - if (capi_message2cmsg(&iif->acmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - send_conf(iif, ap, skb, - CapiResetProcedureNotSupportedByCurrentProtocol); -} - -/* - * unsupported CAPI message handler - */ -static void do_unsupported(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - - /* decode message */ - if (capi_message2cmsg(&iif->acmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); -} - -/* - * CAPI message handler: no-op - */ -static void do_nothing(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - - /* decode message */ - if (capi_message2cmsg(&iif->acmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - dev_kfree_skb_any(skb); -} - -static void do_data_b3_resp(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - dump_rawmsg(DEBUG_MCMD, __func__, skb->data); - dev_kfree_skb_any(skb); -} - -/* table of outgoing CAPI message handlers with lookup function */ -typedef void (*capi_send_handler_t)(struct gigaset_capi_ctr *, - struct gigaset_capi_appl *, - struct sk_buff *); - -static struct { - u16 cmd; - capi_send_handler_t handler; -} capi_send_handler_table[] = { - /* most frequent messages first for faster lookup */ - { CAPI_DATA_B3_REQ, do_data_b3_req }, - { CAPI_DATA_B3_RESP, do_data_b3_resp }, - - { CAPI_ALERT_REQ, do_alert_req }, - { CAPI_CONNECT_ACTIVE_RESP, do_nothing }, - { CAPI_CONNECT_B3_ACTIVE_RESP, do_nothing }, - { CAPI_CONNECT_B3_REQ, do_connect_b3_req }, - { CAPI_CONNECT_B3_RESP, do_connect_b3_resp }, - { CAPI_CONNECT_B3_T90_ACTIVE_RESP, do_nothing }, - { CAPI_CONNECT_REQ, do_connect_req }, - { CAPI_CONNECT_RESP, do_connect_resp }, - { CAPI_DISCONNECT_B3_REQ, do_disconnect_b3_req }, - { CAPI_DISCONNECT_B3_RESP, do_nothing }, - { CAPI_DISCONNECT_REQ, do_disconnect_req }, - { CAPI_DISCONNECT_RESP, do_nothing }, - { CAPI_FACILITY_REQ, do_facility_req }, - { CAPI_FACILITY_RESP, do_nothing }, - { CAPI_LISTEN_REQ, do_listen_req }, - { CAPI_SELECT_B_PROTOCOL_REQ, do_unsupported }, - { CAPI_RESET_B3_REQ, do_reset_b3_req }, - { CAPI_RESET_B3_RESP, do_nothing }, - - /* - * ToDo: support overlap sending (requires ev-layer state - * machine extension to generate additional ATD commands) - */ - { CAPI_INFO_REQ, do_unsupported }, - { CAPI_INFO_RESP, do_nothing }, - - /* - * ToDo: what's the proper response for these? - */ - { CAPI_MANUFACTURER_REQ, do_nothing }, - { CAPI_MANUFACTURER_RESP, do_nothing }, -}; - -/* look up handler */ -static inline capi_send_handler_t lookup_capi_send_handler(const u16 cmd) -{ - size_t i; - - for (i = 0; i < ARRAY_SIZE(capi_send_handler_table); i++) - if (capi_send_handler_table[i].cmd == cmd) - return capi_send_handler_table[i].handler; - return NULL; -} - - -/** - * gigaset_send_message() - accept a CAPI message from an application - * @ctr: controller descriptor structure. - * @skb: CAPI message. - * - * Return value: CAPI error code - * Note: capidrv (and probably others, too) only uses the return value to - * decide whether it has to free the skb (only if result != CAPI_NOERROR (0)) - */ -static u16 gigaset_send_message(struct capi_ctr *ctr, struct sk_buff *skb) -{ - struct gigaset_capi_ctr *iif - = container_of(ctr, struct gigaset_capi_ctr, ctr); - struct cardstate *cs = ctr->driverdata; - struct gigaset_capi_appl *ap; - capi_send_handler_t handler; - - /* can only handle linear sk_buffs */ - if (skb_linearize(skb) < 0) { - dev_warn(cs->dev, "%s: skb_linearize failed\n", __func__); - return CAPI_MSGOSRESOURCEERR; - } - - /* retrieve application data structure */ - ap = get_appl(iif, CAPIMSG_APPID(skb->data)); - if (!ap) { - dev_notice(cs->dev, "%s: application %u not registered\n", - __func__, CAPIMSG_APPID(skb->data)); - return CAPI_ILLAPPNR; - } - - /* look up command */ - handler = lookup_capi_send_handler(CAPIMSG_CMD(skb->data)); - if (!handler) { - /* unknown/unsupported message type */ - if (printk_ratelimit()) - dev_notice(cs->dev, "%s: unsupported message %u\n", - __func__, CAPIMSG_CMD(skb->data)); - return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; - } - - /* serialize */ - if (atomic_add_return(1, &iif->sendqlen) > 1) { - /* queue behind other messages */ - skb_queue_tail(&iif->sendqueue, skb); - return CAPI_NOERROR; - } - - /* process message */ - handler(iif, ap, skb); - - /* process other messages arrived in the meantime */ - while (atomic_sub_return(1, &iif->sendqlen) > 0) { - skb = skb_dequeue(&iif->sendqueue); - if (!skb) { - /* should never happen */ - dev_err(cs->dev, "%s: send queue empty\n", __func__); - continue; - } - ap = get_appl(iif, CAPIMSG_APPID(skb->data)); - if (!ap) { - /* could that happen? */ - dev_warn(cs->dev, "%s: application %u vanished\n", - __func__, CAPIMSG_APPID(skb->data)); - continue; - } - handler = lookup_capi_send_handler(CAPIMSG_CMD(skb->data)); - if (!handler) { - /* should never happen */ - dev_err(cs->dev, "%s: handler %x vanished\n", - __func__, CAPIMSG_CMD(skb->data)); - continue; - } - handler(iif, ap, skb); - } - - return CAPI_NOERROR; -} - -/** - * gigaset_procinfo() - build single line description for controller - * @ctr: controller descriptor structure. - * - * Return value: pointer to generated string (null terminated) - */ -static char *gigaset_procinfo(struct capi_ctr *ctr) -{ - return ctr->name; /* ToDo: more? */ -} - -static int gigaset_proc_show(struct seq_file *m, void *v) -{ - struct capi_ctr *ctr = m->private; - struct cardstate *cs = ctr->driverdata; - char *s; - int i; - - seq_printf(m, "%-16s %s\n", "name", ctr->name); - seq_printf(m, "%-16s %s %s\n", "dev", - dev_driver_string(cs->dev), dev_name(cs->dev)); - seq_printf(m, "%-16s %d\n", "id", cs->myid); - if (cs->gotfwver) - seq_printf(m, "%-16s %d.%d.%d.%d\n", "firmware", - cs->fwver[0], cs->fwver[1], cs->fwver[2], cs->fwver[3]); - seq_printf(m, "%-16s %d\n", "channels", cs->channels); - seq_printf(m, "%-16s %s\n", "onechannel", cs->onechannel ? "yes" : "no"); - - switch (cs->mode) { - case M_UNKNOWN: - s = "unknown"; - break; - case M_CONFIG: - s = "config"; - break; - case M_UNIMODEM: - s = "Unimodem"; - break; - case M_CID: - s = "CID"; - break; - default: - s = "??"; - } - seq_printf(m, "%-16s %s\n", "mode", s); - - switch (cs->mstate) { - case MS_UNINITIALIZED: - s = "uninitialized"; - break; - case MS_INIT: - s = "init"; - break; - case MS_LOCKED: - s = "locked"; - break; - case MS_SHUTDOWN: - s = "shutdown"; - break; - case MS_RECOVER: - s = "recover"; - break; - case MS_READY: - s = "ready"; - break; - default: - s = "??"; - } - seq_printf(m, "%-16s %s\n", "mstate", s); - - seq_printf(m, "%-16s %s\n", "running", cs->running ? "yes" : "no"); - seq_printf(m, "%-16s %s\n", "connected", cs->connected ? "yes" : "no"); - seq_printf(m, "%-16s %s\n", "isdn_up", cs->isdn_up ? "yes" : "no"); - seq_printf(m, "%-16s %s\n", "cidmode", cs->cidmode ? "yes" : "no"); - - for (i = 0; i < cs->channels; i++) { - seq_printf(m, "[%d]%-13s %d\n", i, "corrupted", - cs->bcs[i].corrupted); - seq_printf(m, "[%d]%-13s %d\n", i, "trans_down", - cs->bcs[i].trans_down); - seq_printf(m, "[%d]%-13s %d\n", i, "trans_up", - cs->bcs[i].trans_up); - seq_printf(m, "[%d]%-13s %d\n", i, "chstate", - cs->bcs[i].chstate); - switch (cs->bcs[i].proto2) { - case L2_BITSYNC: - s = "bitsync"; - break; - case L2_HDLC: - s = "HDLC"; - break; - case L2_VOICE: - s = "voice"; - break; - default: - s = "??"; - } - seq_printf(m, "[%d]%-13s %s\n", i, "proto2", s); - } - return 0; -} - -/** - * gigaset_isdn_regdev() - register device to LL - * @cs: device descriptor structure. - * @isdnid: device name. - * - * Return value: 0 on success, error code < 0 on failure - */ -int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid) -{ - struct gigaset_capi_ctr *iif; - int rc; - - iif = kzalloc(sizeof(*iif), GFP_KERNEL); - if (!iif) { - pr_err("%s: out of memory\n", __func__); - return -ENOMEM; - } - - /* prepare controller structure */ - iif->ctr.owner = THIS_MODULE; - iif->ctr.driverdata = cs; - strncpy(iif->ctr.name, isdnid, sizeof(iif->ctr.name) - 1); - iif->ctr.driver_name = "gigaset"; - iif->ctr.load_firmware = NULL; - iif->ctr.reset_ctr = NULL; - iif->ctr.register_appl = gigaset_register_appl; - iif->ctr.release_appl = gigaset_release_appl; - iif->ctr.send_message = gigaset_send_message; - iif->ctr.procinfo = gigaset_procinfo; - iif->ctr.proc_show = gigaset_proc_show, - INIT_LIST_HEAD(&iif->appls); - skb_queue_head_init(&iif->sendqueue); - atomic_set(&iif->sendqlen, 0); - - /* register controller with CAPI */ - rc = attach_capi_ctr(&iif->ctr); - if (rc) { - pr_err("attach_capi_ctr failed (%d)\n", rc); - kfree(iif); - return rc; - } - - cs->iif = iif; - cs->hw_hdr_len = CAPI_DATA_B3_REQ_LEN; - return 0; -} - -/** - * gigaset_isdn_unregdev() - unregister device from LL - * @cs: device descriptor structure. - */ -void gigaset_isdn_unregdev(struct cardstate *cs) -{ - struct gigaset_capi_ctr *iif = cs->iif; - - detach_capi_ctr(&iif->ctr); - kfree(iif); - cs->iif = NULL; -} - -static struct capi_driver capi_driver_gigaset = { - .name = "gigaset", - .revision = "1.0", -}; - -/** - * gigaset_isdn_regdrv() - register driver to LL - */ -void gigaset_isdn_regdrv(void) -{ - pr_info("Kernel CAPI interface\n"); - register_capi_driver(&capi_driver_gigaset); -} - -/** - * gigaset_isdn_unregdrv() - unregister driver from LL - */ -void gigaset_isdn_unregdrv(void) -{ - unregister_capi_driver(&capi_driver_gigaset); -} diff --git a/drivers/staging/isdn/gigaset/common.c b/drivers/staging/isdn/gigaset/common.c deleted file mode 100644 index 3bb8092858ab..000000000000 --- a/drivers/staging/isdn/gigaset/common.c +++ /dev/null @@ -1,1153 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Stuff used by all variants of the driver - * - * Copyright (c) 2001 by Stefan Eilers, - * Hansjoerg Lipp , - * Tilman Schmidt . - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include - -/* Version Information */ -#define DRIVER_AUTHOR "Hansjoerg Lipp , Tilman Schmidt , Stefan Eilers" -#define DRIVER_DESC "Driver for Gigaset 307x" - -#ifdef CONFIG_GIGASET_DEBUG -#define DRIVER_DESC_DEBUG " (debug build)" -#else -#define DRIVER_DESC_DEBUG "" -#endif - -/* Module parameters */ -int gigaset_debuglevel; -EXPORT_SYMBOL_GPL(gigaset_debuglevel); -module_param_named(debug, gigaset_debuglevel, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "debug level"); - -/* driver state flags */ -#define VALID_MINOR 0x01 -#define VALID_ID 0x02 - -/** - * gigaset_dbg_buffer() - dump data in ASCII and hex for debugging - * @level: debugging level. - * @msg: message prefix. - * @len: number of bytes to dump. - * @buf: data to dump. - * - * If the current debugging level includes one of the bits set in @level, - * @len bytes starting at @buf are logged to dmesg at KERN_DEBUG prio, - * prefixed by the text @msg. - */ -void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, - size_t len, const unsigned char *buf) -{ - unsigned char outbuf[80]; - unsigned char c; - size_t space = sizeof outbuf - 1; - unsigned char *out = outbuf; - size_t numin = len; - - while (numin--) { - c = *buf++; - if (c == '~' || c == '^' || c == '\\') { - if (!space--) - break; - *out++ = '\\'; - } - if (c & 0x80) { - if (!space--) - break; - *out++ = '~'; - c ^= 0x80; - } - if (c < 0x20 || c == 0x7f) { - if (!space--) - break; - *out++ = '^'; - c ^= 0x40; - } - if (!space--) - break; - *out++ = c; - } - *out = 0; - - gig_dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf); -} -EXPORT_SYMBOL_GPL(gigaset_dbg_buffer); - -static int setflags(struct cardstate *cs, unsigned flags, unsigned delay) -{ - int r; - - r = cs->ops->set_modem_ctrl(cs, cs->control_state, flags); - cs->control_state = flags; - if (r < 0) - return r; - - if (delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(delay * HZ / 1000); - } - - return 0; -} - -int gigaset_enterconfigmode(struct cardstate *cs) -{ - int i, r; - - cs->control_state = TIOCM_RTS; - - r = setflags(cs, TIOCM_DTR, 200); - if (r < 0) - goto error; - r = setflags(cs, 0, 200); - if (r < 0) - goto error; - for (i = 0; i < 5; ++i) { - r = setflags(cs, TIOCM_RTS, 100); - if (r < 0) - goto error; - r = setflags(cs, 0, 100); - if (r < 0) - goto error; - } - r = setflags(cs, TIOCM_RTS | TIOCM_DTR, 800); - if (r < 0) - goto error; - - return 0; - -error: - dev_err(cs->dev, "error %d on setuartbits\n", -r); - cs->control_state = TIOCM_RTS | TIOCM_DTR; - cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS | TIOCM_DTR); - - return -1; -} - -static int test_timeout(struct at_state_t *at_state) -{ - if (!at_state->timer_expires) - return 0; - - if (--at_state->timer_expires) { - gig_dbg(DEBUG_MCMD, "decreased timer of %p to %lu", - at_state, at_state->timer_expires); - return 0; - } - - gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, - at_state->timer_index, NULL); - return 1; -} - -static void timer_tick(struct timer_list *t) -{ - struct cardstate *cs = from_timer(cs, t, timer); - unsigned long flags; - unsigned channel; - struct at_state_t *at_state; - int timeout = 0; - - spin_lock_irqsave(&cs->lock, flags); - - for (channel = 0; channel < cs->channels; ++channel) - if (test_timeout(&cs->bcs[channel].at_state)) - timeout = 1; - - if (test_timeout(&cs->at_state)) - timeout = 1; - - list_for_each_entry(at_state, &cs->temp_at_states, list) - if (test_timeout(at_state)) - timeout = 1; - - if (cs->running) { - mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK)); - if (timeout) { - gig_dbg(DEBUG_EVENT, "scheduling timeout"); - tasklet_schedule(&cs->event_tasklet); - } - } - - spin_unlock_irqrestore(&cs->lock, flags); -} - -int gigaset_get_channel(struct bc_state *bcs) -{ - unsigned long flags; - - spin_lock_irqsave(&bcs->cs->lock, flags); - if (bcs->use_count || !try_module_get(bcs->cs->driver->owner)) { - gig_dbg(DEBUG_CHANNEL, "could not allocate channel %d", - bcs->channel); - spin_unlock_irqrestore(&bcs->cs->lock, flags); - return -EBUSY; - } - ++bcs->use_count; - bcs->busy = 1; - gig_dbg(DEBUG_CHANNEL, "allocated channel %d", bcs->channel); - spin_unlock_irqrestore(&bcs->cs->lock, flags); - return 0; -} - -struct bc_state *gigaset_get_free_channel(struct cardstate *cs) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&cs->lock, flags); - if (!try_module_get(cs->driver->owner)) { - gig_dbg(DEBUG_CHANNEL, - "could not get module for allocating channel"); - spin_unlock_irqrestore(&cs->lock, flags); - return NULL; - } - for (i = 0; i < cs->channels; ++i) - if (!cs->bcs[i].use_count) { - ++cs->bcs[i].use_count; - cs->bcs[i].busy = 1; - spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_CHANNEL, "allocated channel %d", i); - return cs->bcs + i; - } - module_put(cs->driver->owner); - spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_CHANNEL, "no free channel"); - return NULL; -} - -void gigaset_free_channel(struct bc_state *bcs) -{ - unsigned long flags; - - spin_lock_irqsave(&bcs->cs->lock, flags); - if (!bcs->busy) { - gig_dbg(DEBUG_CHANNEL, "could not free channel %d", - bcs->channel); - spin_unlock_irqrestore(&bcs->cs->lock, flags); - return; - } - --bcs->use_count; - bcs->busy = 0; - module_put(bcs->cs->driver->owner); - gig_dbg(DEBUG_CHANNEL, "freed channel %d", bcs->channel); - spin_unlock_irqrestore(&bcs->cs->lock, flags); -} - -int gigaset_get_channels(struct cardstate *cs) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&cs->lock, flags); - for (i = 0; i < cs->channels; ++i) - if (cs->bcs[i].use_count) { - spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_CHANNEL, - "could not allocate all channels"); - return -EBUSY; - } - for (i = 0; i < cs->channels; ++i) - ++cs->bcs[i].use_count; - spin_unlock_irqrestore(&cs->lock, flags); - - gig_dbg(DEBUG_CHANNEL, "allocated all channels"); - - return 0; -} - -void gigaset_free_channels(struct cardstate *cs) -{ - unsigned long flags; - int i; - - gig_dbg(DEBUG_CHANNEL, "unblocking all channels"); - spin_lock_irqsave(&cs->lock, flags); - for (i = 0; i < cs->channels; ++i) - --cs->bcs[i].use_count; - spin_unlock_irqrestore(&cs->lock, flags); -} - -void gigaset_block_channels(struct cardstate *cs) -{ - unsigned long flags; - int i; - - gig_dbg(DEBUG_CHANNEL, "blocking all channels"); - spin_lock_irqsave(&cs->lock, flags); - for (i = 0; i < cs->channels; ++i) - ++cs->bcs[i].use_count; - spin_unlock_irqrestore(&cs->lock, flags); -} - -static void clear_events(struct cardstate *cs) -{ - struct event_t *ev; - unsigned head, tail; - unsigned long flags; - - spin_lock_irqsave(&cs->ev_lock, flags); - - head = cs->ev_head; - tail = cs->ev_tail; - - while (tail != head) { - ev = cs->events + head; - kfree(ev->ptr); - head = (head + 1) % MAX_EVENTS; - } - - cs->ev_head = tail; - - spin_unlock_irqrestore(&cs->ev_lock, flags); -} - -/** - * gigaset_add_event() - add event to device event queue - * @cs: device descriptor structure. - * @at_state: connection state structure. - * @type: event type. - * @ptr: pointer parameter for event. - * @parameter: integer parameter for event. - * @arg: pointer parameter for event. - * - * Allocate an event queue entry from the device's event queue, and set it up - * with the parameters given. - * - * Return value: added event - */ -struct event_t *gigaset_add_event(struct cardstate *cs, - struct at_state_t *at_state, int type, - void *ptr, int parameter, void *arg) -{ - unsigned long flags; - unsigned next, tail; - struct event_t *event = NULL; - - gig_dbg(DEBUG_EVENT, "queueing event %d", type); - - spin_lock_irqsave(&cs->ev_lock, flags); - - tail = cs->ev_tail; - next = (tail + 1) % MAX_EVENTS; - if (unlikely(next == cs->ev_head)) - dev_err(cs->dev, "event queue full\n"); - else { - event = cs->events + tail; - event->type = type; - event->at_state = at_state; - event->cid = -1; - event->ptr = ptr; - event->arg = arg; - event->parameter = parameter; - cs->ev_tail = next; - } - - spin_unlock_irqrestore(&cs->ev_lock, flags); - - return event; -} -EXPORT_SYMBOL_GPL(gigaset_add_event); - -static void clear_at_state(struct at_state_t *at_state) -{ - int i; - - for (i = 0; i < STR_NUM; ++i) { - kfree(at_state->str_var[i]); - at_state->str_var[i] = NULL; - } -} - -static void dealloc_temp_at_states(struct cardstate *cs) -{ - struct at_state_t *cur, *next; - - list_for_each_entry_safe(cur, next, &cs->temp_at_states, list) { - list_del(&cur->list); - clear_at_state(cur); - kfree(cur); - } -} - -static void gigaset_freebcs(struct bc_state *bcs) -{ - int i; - - gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); - bcs->cs->ops->freebcshw(bcs); - - gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); - clear_at_state(&bcs->at_state); - gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); - dev_kfree_skb(bcs->rx_skb); - bcs->rx_skb = NULL; - - for (i = 0; i < AT_NUM; ++i) { - kfree(bcs->commands[i]); - bcs->commands[i] = NULL; - } -} - -static struct cardstate *alloc_cs(struct gigaset_driver *drv) -{ - unsigned long flags; - unsigned i; - struct cardstate *cs; - struct cardstate *ret = NULL; - - spin_lock_irqsave(&drv->lock, flags); - if (drv->blocked) - goto exit; - for (i = 0; i < drv->minors; ++i) { - cs = drv->cs + i; - if (!(cs->flags & VALID_MINOR)) { - cs->flags = VALID_MINOR; - ret = cs; - break; - } - } -exit: - spin_unlock_irqrestore(&drv->lock, flags); - return ret; -} - -static void free_cs(struct cardstate *cs) -{ - cs->flags = 0; -} - -static void make_valid(struct cardstate *cs, unsigned mask) -{ - unsigned long flags; - struct gigaset_driver *drv = cs->driver; - spin_lock_irqsave(&drv->lock, flags); - cs->flags |= mask; - spin_unlock_irqrestore(&drv->lock, flags); -} - -static void make_invalid(struct cardstate *cs, unsigned mask) -{ - unsigned long flags; - struct gigaset_driver *drv = cs->driver; - spin_lock_irqsave(&drv->lock, flags); - cs->flags &= ~mask; - spin_unlock_irqrestore(&drv->lock, flags); -} - -/** - * gigaset_freecs() - free all associated ressources of a device - * @cs: device descriptor structure. - * - * Stops all tasklets and timers, unregisters the device from all - * subsystems it was registered to, deallocates the device structure - * @cs and all structures referenced from it. - * Operations on the device should be stopped before calling this. - */ -void gigaset_freecs(struct cardstate *cs) -{ - int i; - unsigned long flags; - - if (!cs) - return; - - mutex_lock(&cs->mutex); - - spin_lock_irqsave(&cs->lock, flags); - cs->running = 0; - spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are - not rescheduled below */ - - tasklet_kill(&cs->event_tasklet); - del_timer_sync(&cs->timer); - - switch (cs->cs_init) { - default: - /* clear B channel structures */ - for (i = 0; i < cs->channels; ++i) { - gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i); - gigaset_freebcs(cs->bcs + i); - } - - /* clear device sysfs */ - gigaset_free_dev_sysfs(cs); - - gigaset_if_free(cs); - - gig_dbg(DEBUG_INIT, "clearing hw"); - cs->ops->freecshw(cs); - - /* fall through */ - case 2: /* error in initcshw */ - /* Deregister from LL */ - make_invalid(cs, VALID_ID); - gigaset_isdn_unregdev(cs); - - /* fall through */ - case 1: /* error when registering to LL */ - gig_dbg(DEBUG_INIT, "clearing at_state"); - clear_at_state(&cs->at_state); - dealloc_temp_at_states(cs); - clear_events(cs); - tty_port_destroy(&cs->port); - - /* fall through */ - case 0: /* error in basic setup */ - gig_dbg(DEBUG_INIT, "freeing inbuf"); - kfree(cs->inbuf); - kfree(cs->bcs); - } - - mutex_unlock(&cs->mutex); - free_cs(cs); -} -EXPORT_SYMBOL_GPL(gigaset_freecs); - -void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, - struct cardstate *cs, int cid) -{ - int i; - - INIT_LIST_HEAD(&at_state->list); - at_state->waiting = 0; - at_state->getstring = 0; - at_state->pending_commands = 0; - at_state->timer_expires = 0; - at_state->timer_active = 0; - at_state->timer_index = 0; - at_state->seq_index = 0; - at_state->ConState = 0; - for (i = 0; i < STR_NUM; ++i) - at_state->str_var[i] = NULL; - at_state->int_var[VAR_ZDLE] = 0; - at_state->int_var[VAR_ZCTP] = -1; - at_state->int_var[VAR_ZSAU] = ZSAU_NULL; - at_state->cs = cs; - at_state->bcs = bcs; - at_state->cid = cid; - if (!cid) - at_state->replystruct = cs->tabnocid; - else - at_state->replystruct = cs->tabcid; -} - - -static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs) -/* inbuf->read must be allocated before! */ -{ - inbuf->head = 0; - inbuf->tail = 0; - inbuf->cs = cs; - inbuf->inputstate = INS_command; -} - -/** - * gigaset_fill_inbuf() - append received data to input buffer - * @inbuf: buffer structure. - * @src: received data. - * @numbytes: number of bytes received. - * - * Return value: !=0 if some data was appended - */ -int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, - unsigned numbytes) -{ - unsigned n, head, tail, bytesleft; - - gig_dbg(DEBUG_INTR, "received %u bytes", numbytes); - - if (!numbytes) - return 0; - - bytesleft = numbytes; - tail = inbuf->tail; - head = inbuf->head; - gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); - - while (bytesleft) { - if (head > tail) - n = head - 1 - tail; - else if (head == 0) - n = (RBUFSIZE - 1) - tail; - else - n = RBUFSIZE - tail; - if (!n) { - dev_err(inbuf->cs->dev, - "buffer overflow (%u bytes lost)\n", - bytesleft); - break; - } - if (n > bytesleft) - n = bytesleft; - memcpy(inbuf->data + tail, src, n); - bytesleft -= n; - tail = (tail + n) % RBUFSIZE; - src += n; - } - gig_dbg(DEBUG_INTR, "setting tail to %u", tail); - inbuf->tail = tail; - return numbytes != bytesleft; -} -EXPORT_SYMBOL_GPL(gigaset_fill_inbuf); - -/* Initialize the b-channel structure */ -static int gigaset_initbcs(struct bc_state *bcs, struct cardstate *cs, - int channel) -{ - int i; - - bcs->tx_skb = NULL; - - skb_queue_head_init(&bcs->squeue); - - bcs->corrupted = 0; - bcs->trans_down = 0; - bcs->trans_up = 0; - - gig_dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel); - gigaset_at_init(&bcs->at_state, bcs, cs, -1); - -#ifdef CONFIG_GIGASET_DEBUG - bcs->emptycount = 0; -#endif - - bcs->rx_bufsize = 0; - bcs->rx_skb = NULL; - bcs->rx_fcs = PPP_INITFCS; - bcs->inputstate = 0; - bcs->channel = channel; - bcs->cs = cs; - - bcs->chstate = 0; - bcs->use_count = 1; - bcs->busy = 0; - bcs->ignore = cs->ignoreframes; - - for (i = 0; i < AT_NUM; ++i) - bcs->commands[i] = NULL; - - spin_lock_init(&bcs->aplock); - bcs->ap = NULL; - bcs->apconnstate = 0; - - gig_dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel); - return cs->ops->initbcshw(bcs); -} - -/** - * gigaset_initcs() - initialize device structure - * @drv: hardware driver the device belongs to - * @channels: number of B channels supported by device - * @onechannel: !=0 if B channel data and AT commands share one - * communication channel (M10x), - * ==0 if B channels have separate communication channels (base) - * @ignoreframes: number of frames to ignore after setting up B channel - * @cidmode: !=0: start in CallID mode - * @modulename: name of driver module for LL registration - * - * Allocate and initialize cardstate structure for Gigaset driver - * Calls hardware dependent gigaset_initcshw() function - * Calls B channel initialization function gigaset_initbcs() for each B channel - * - * Return value: - * pointer to cardstate structure - */ -struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, - int onechannel, int ignoreframes, - int cidmode, const char *modulename) -{ - struct cardstate *cs; - unsigned long flags; - int i; - - gig_dbg(DEBUG_INIT, "allocating cs"); - cs = alloc_cs(drv); - if (!cs) { - pr_err("maximum number of devices exceeded\n"); - return NULL; - } - - cs->cs_init = 0; - cs->channels = channels; - cs->onechannel = onechannel; - cs->ignoreframes = ignoreframes; - INIT_LIST_HEAD(&cs->temp_at_states); - cs->running = 0; - timer_setup(&cs->timer, timer_tick, 0); - spin_lock_init(&cs->ev_lock); - cs->ev_tail = 0; - cs->ev_head = 0; - - tasklet_init(&cs->event_tasklet, gigaset_handle_event, - (unsigned long) cs); - tty_port_init(&cs->port); - cs->commands_pending = 0; - cs->cur_at_seq = 0; - cs->gotfwver = -1; - cs->dev = NULL; - cs->tty_dev = NULL; - cs->cidmode = cidmode != 0; - cs->tabnocid = gigaset_tab_nocid; - cs->tabcid = gigaset_tab_cid; - - init_waitqueue_head(&cs->waitqueue); - cs->waiting = 0; - - cs->mode = M_UNKNOWN; - cs->mstate = MS_UNINITIALIZED; - - cs->bcs = kmalloc_array(channels, sizeof(struct bc_state), GFP_KERNEL); - cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL); - if (!cs->bcs || !cs->inbuf) { - pr_err("out of memory\n"); - goto error; - } - ++cs->cs_init; - - gig_dbg(DEBUG_INIT, "setting up at_state"); - spin_lock_init(&cs->lock); - gigaset_at_init(&cs->at_state, NULL, cs, 0); - cs->dle = 0; - cs->cbytes = 0; - - gig_dbg(DEBUG_INIT, "setting up inbuf"); - gigaset_inbuf_init(cs->inbuf, cs); - - cs->connected = 0; - cs->isdn_up = 0; - - gig_dbg(DEBUG_INIT, "setting up cmdbuf"); - cs->cmdbuf = cs->lastcmdbuf = NULL; - spin_lock_init(&cs->cmdlock); - cs->curlen = 0; - cs->cmdbytes = 0; - - gig_dbg(DEBUG_INIT, "setting up iif"); - if (gigaset_isdn_regdev(cs, modulename) < 0) { - pr_err("error registering ISDN device\n"); - goto error; - } - - make_valid(cs, VALID_ID); - ++cs->cs_init; - gig_dbg(DEBUG_INIT, "setting up hw"); - if (cs->ops->initcshw(cs) < 0) - goto error; - - ++cs->cs_init; - - /* set up character device */ - gigaset_if_init(cs); - - /* set up device sysfs */ - gigaset_init_dev_sysfs(cs); - - /* set up channel data structures */ - for (i = 0; i < channels; ++i) { - gig_dbg(DEBUG_INIT, "setting up bcs[%d]", i); - if (gigaset_initbcs(cs->bcs + i, cs, i) < 0) { - pr_err("could not allocate channel %d data\n", i); - goto error; - } - } - - spin_lock_irqsave(&cs->lock, flags); - cs->running = 1; - spin_unlock_irqrestore(&cs->lock, flags); - cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK); - add_timer(&cs->timer); - - gig_dbg(DEBUG_INIT, "cs initialized"); - return cs; - -error: - gig_dbg(DEBUG_INIT, "failed"); - gigaset_freecs(cs); - return NULL; -} -EXPORT_SYMBOL_GPL(gigaset_initcs); - -/* ReInitialize the b-channel structure on hangup */ -void gigaset_bcs_reinit(struct bc_state *bcs) -{ - struct sk_buff *skb; - struct cardstate *cs = bcs->cs; - unsigned long flags; - - while ((skb = skb_dequeue(&bcs->squeue)) != NULL) - dev_kfree_skb(skb); - - spin_lock_irqsave(&cs->lock, flags); - clear_at_state(&bcs->at_state); - bcs->at_state.ConState = 0; - bcs->at_state.timer_active = 0; - bcs->at_state.timer_expires = 0; - bcs->at_state.cid = -1; /* No CID defined */ - spin_unlock_irqrestore(&cs->lock, flags); - - bcs->inputstate = 0; - -#ifdef CONFIG_GIGASET_DEBUG - bcs->emptycount = 0; -#endif - - bcs->rx_fcs = PPP_INITFCS; - bcs->chstate = 0; - - bcs->ignore = cs->ignoreframes; - dev_kfree_skb(bcs->rx_skb); - bcs->rx_skb = NULL; - - cs->ops->reinitbcshw(bcs); -} - -static void cleanup_cs(struct cardstate *cs) -{ - struct cmdbuf_t *cb, *tcb; - int i; - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - - cs->mode = M_UNKNOWN; - cs->mstate = MS_UNINITIALIZED; - - clear_at_state(&cs->at_state); - dealloc_temp_at_states(cs); - gigaset_at_init(&cs->at_state, NULL, cs, 0); - - cs->inbuf->inputstate = INS_command; - cs->inbuf->head = 0; - cs->inbuf->tail = 0; - - cb = cs->cmdbuf; - while (cb) { - tcb = cb; - cb = cb->next; - kfree(tcb); - } - cs->cmdbuf = cs->lastcmdbuf = NULL; - cs->curlen = 0; - cs->cmdbytes = 0; - cs->gotfwver = -1; - cs->dle = 0; - cs->cur_at_seq = 0; - cs->commands_pending = 0; - cs->cbytes = 0; - - spin_unlock_irqrestore(&cs->lock, flags); - - for (i = 0; i < cs->channels; ++i) { - gigaset_freebcs(cs->bcs + i); - if (gigaset_initbcs(cs->bcs + i, cs, i) < 0) - pr_err("could not allocate channel %d data\n", i); - } - - if (cs->waiting) { - cs->cmd_result = -ENODEV; - cs->waiting = 0; - wake_up_interruptible(&cs->waitqueue); - } -} - - -/** - * gigaset_start() - start device operations - * @cs: device descriptor structure. - * - * Prepares the device for use by setting up communication parameters, - * scheduling an EV_START event to initiate device initialization, and - * waiting for completion of the initialization. - * - * Return value: - * 0 on success, error code < 0 on failure - */ -int gigaset_start(struct cardstate *cs) -{ - unsigned long flags; - - if (mutex_lock_interruptible(&cs->mutex)) - return -EBUSY; - - spin_lock_irqsave(&cs->lock, flags); - cs->connected = 1; - spin_unlock_irqrestore(&cs->lock, flags); - - if (cs->mstate != MS_LOCKED) { - cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR | TIOCM_RTS); - cs->ops->baud_rate(cs, B115200); - cs->ops->set_line_ctrl(cs, CS8); - cs->control_state = TIOCM_DTR | TIOCM_RTS; - } - - cs->waiting = 1; - - if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) { - cs->waiting = 0; - goto error; - } - gigaset_schedule_event(cs); - - wait_event(cs->waitqueue, !cs->waiting); - - mutex_unlock(&cs->mutex); - return 0; - -error: - mutex_unlock(&cs->mutex); - return -ENOMEM; -} -EXPORT_SYMBOL_GPL(gigaset_start); - -/** - * gigaset_shutdown() - shut down device operations - * @cs: device descriptor structure. - * - * Deactivates the device by scheduling an EV_SHUTDOWN event and - * waiting for completion of the shutdown. - * - * Return value: - * 0 - success, -ENODEV - error (no device associated) - */ -int gigaset_shutdown(struct cardstate *cs) -{ - mutex_lock(&cs->mutex); - - if (!(cs->flags & VALID_MINOR)) { - mutex_unlock(&cs->mutex); - return -ENODEV; - } - - cs->waiting = 1; - - if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) - goto exit; - gigaset_schedule_event(cs); - - wait_event(cs->waitqueue, !cs->waiting); - - cleanup_cs(cs); - -exit: - mutex_unlock(&cs->mutex); - return 0; -} -EXPORT_SYMBOL_GPL(gigaset_shutdown); - -/** - * gigaset_stop() - stop device operations - * @cs: device descriptor structure. - * - * Stops operations on the device by scheduling an EV_STOP event and - * waiting for completion of the shutdown. - */ -void gigaset_stop(struct cardstate *cs) -{ - mutex_lock(&cs->mutex); - - cs->waiting = 1; - - if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) - goto exit; - gigaset_schedule_event(cs); - - wait_event(cs->waitqueue, !cs->waiting); - - cleanup_cs(cs); - -exit: - mutex_unlock(&cs->mutex); -} -EXPORT_SYMBOL_GPL(gigaset_stop); - -static LIST_HEAD(drivers); -static DEFINE_SPINLOCK(driver_lock); - -struct cardstate *gigaset_get_cs_by_id(int id) -{ - unsigned long flags; - struct cardstate *ret = NULL; - struct cardstate *cs; - struct gigaset_driver *drv; - unsigned i; - - spin_lock_irqsave(&driver_lock, flags); - list_for_each_entry(drv, &drivers, list) { - spin_lock(&drv->lock); - for (i = 0; i < drv->minors; ++i) { - cs = drv->cs + i; - if ((cs->flags & VALID_ID) && cs->myid == id) { - ret = cs; - break; - } - } - spin_unlock(&drv->lock); - if (ret) - break; - } - spin_unlock_irqrestore(&driver_lock, flags); - return ret; -} - -static struct cardstate *gigaset_get_cs_by_minor(unsigned minor) -{ - unsigned long flags; - struct cardstate *ret = NULL; - struct gigaset_driver *drv; - unsigned index; - - spin_lock_irqsave(&driver_lock, flags); - list_for_each_entry(drv, &drivers, list) { - if (minor < drv->minor || minor >= drv->minor + drv->minors) - continue; - index = minor - drv->minor; - spin_lock(&drv->lock); - if (drv->cs[index].flags & VALID_MINOR) - ret = drv->cs + index; - spin_unlock(&drv->lock); - if (ret) - break; - } - spin_unlock_irqrestore(&driver_lock, flags); - return ret; -} - -struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty) -{ - return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start); -} - -/** - * gigaset_freedriver() - free all associated ressources of a driver - * @drv: driver descriptor structure. - * - * Unregisters the driver from the system and deallocates the driver - * structure @drv and all structures referenced from it. - * All devices should be shut down before calling this. - */ -void gigaset_freedriver(struct gigaset_driver *drv) -{ - unsigned long flags; - - spin_lock_irqsave(&driver_lock, flags); - list_del(&drv->list); - spin_unlock_irqrestore(&driver_lock, flags); - - gigaset_if_freedriver(drv); - - kfree(drv->cs); - kfree(drv); -} -EXPORT_SYMBOL_GPL(gigaset_freedriver); - -/** - * gigaset_initdriver() - initialize driver structure - * @minor: First minor number - * @minors: Number of minors this driver can handle - * @procname: Name of the driver - * @devname: Name of the device files (prefix without minor number) - * - * Allocate and initialize gigaset_driver structure. Initialize interface. - * - * Return value: - * Pointer to the gigaset_driver structure on success, NULL on failure. - */ -struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, - const char *procname, - const char *devname, - const struct gigaset_ops *ops, - struct module *owner) -{ - struct gigaset_driver *drv; - unsigned long flags; - unsigned i; - - drv = kmalloc(sizeof *drv, GFP_KERNEL); - if (!drv) - return NULL; - - drv->have_tty = 0; - drv->minor = minor; - drv->minors = minors; - spin_lock_init(&drv->lock); - drv->blocked = 0; - drv->ops = ops; - drv->owner = owner; - INIT_LIST_HEAD(&drv->list); - - drv->cs = kmalloc_array(minors, sizeof(*drv->cs), GFP_KERNEL); - if (!drv->cs) - goto error; - - for (i = 0; i < minors; ++i) { - drv->cs[i].flags = 0; - drv->cs[i].driver = drv; - drv->cs[i].ops = drv->ops; - drv->cs[i].minor_index = i; - mutex_init(&drv->cs[i].mutex); - } - - gigaset_if_initdriver(drv, procname, devname); - - spin_lock_irqsave(&driver_lock, flags); - list_add(&drv->list, &drivers); - spin_unlock_irqrestore(&driver_lock, flags); - - return drv; - -error: - kfree(drv); - return NULL; -} -EXPORT_SYMBOL_GPL(gigaset_initdriver); - -/** - * gigaset_blockdriver() - block driver - * @drv: driver descriptor structure. - * - * Prevents the driver from attaching new devices, in preparation for - * deregistration. - */ -void gigaset_blockdriver(struct gigaset_driver *drv) -{ - drv->blocked = 1; -} -EXPORT_SYMBOL_GPL(gigaset_blockdriver); - -static int __init gigaset_init_module(void) -{ - /* in accordance with the principle of least astonishment, - * setting the 'debug' parameter to 1 activates a sensible - * set of default debug levels - */ - if (gigaset_debuglevel == 1) - gigaset_debuglevel = DEBUG_DEFAULT; - - pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n"); - gigaset_isdn_regdrv(); - return 0; -} - -static void __exit gigaset_exit_module(void) -{ - gigaset_isdn_unregdrv(); -} - -module_init(gigaset_init_module); -module_exit(gigaset_exit_module); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); - -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/isdn/gigaset/dummyll.c b/drivers/staging/isdn/gigaset/dummyll.c deleted file mode 100644 index 4b9637e5da6e..000000000000 --- a/drivers/staging/isdn/gigaset/dummyll.c +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Dummy LL interface for the Gigaset driver - * - * Copyright (c) 2009 by Tilman Schmidt . - * - * ===================================================================== - * ===================================================================== - */ - -#include -#include "gigaset.h" - -void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) -{ -} -EXPORT_SYMBOL_GPL(gigaset_skb_sent); - -void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) -{ -} -EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); - -void gigaset_isdn_rcv_err(struct bc_state *bcs) -{ -} -EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); - -int gigaset_isdn_icall(struct at_state_t *at_state) -{ - return ICALL_IGNORE; -} - -void gigaset_isdn_connD(struct bc_state *bcs) -{ -} - -void gigaset_isdn_hupD(struct bc_state *bcs) -{ -} - -void gigaset_isdn_connB(struct bc_state *bcs) -{ -} - -void gigaset_isdn_hupB(struct bc_state *bcs) -{ -} - -void gigaset_isdn_start(struct cardstate *cs) -{ -} - -void gigaset_isdn_stop(struct cardstate *cs) -{ -} - -int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid) -{ - return 0; -} - -void gigaset_isdn_unregdev(struct cardstate *cs) -{ -} - -void gigaset_isdn_regdrv(void) -{ - pr_info("no ISDN subsystem interface\n"); -} - -void gigaset_isdn_unregdrv(void) -{ -} diff --git a/drivers/staging/isdn/gigaset/ev-layer.c b/drivers/staging/isdn/gigaset/ev-layer.c deleted file mode 100644 index f8bb1869c600..000000000000 --- a/drivers/staging/isdn/gigaset/ev-layer.c +++ /dev/null @@ -1,1910 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Stuff used by all variants of the driver - * - * Copyright (c) 2001 by Stefan Eilers, - * Hansjoerg Lipp , - * Tilman Schmidt . - * - * ===================================================================== - * ===================================================================== - */ - -#include -#include "gigaset.h" - -/* ========================================================== */ -/* bit masks for pending commands */ -#define PC_DIAL 0x001 -#define PC_HUP 0x002 -#define PC_INIT 0x004 -#define PC_DLE0 0x008 -#define PC_DLE1 0x010 -#define PC_SHUTDOWN 0x020 -#define PC_ACCEPT 0x040 -#define PC_CID 0x080 -#define PC_NOCID 0x100 -#define PC_CIDMODE 0x200 -#define PC_UMMODE 0x400 - -/* types of modem responses */ -#define RT_NOTHING 0 -#define RT_ZSAU 1 -#define RT_RING 2 -#define RT_NUMBER 3 -#define RT_STRING 4 -#define RT_ZCAU 6 - -/* Possible ASCII responses */ -#define RSP_OK 0 -#define RSP_ERROR 1 -#define RSP_ZGCI 3 -#define RSP_RING 4 -#define RSP_ZVLS 5 -#define RSP_ZCAU 6 - -/* responses with values to store in at_state */ -/* - numeric */ -#define RSP_VAR 100 -#define RSP_ZSAU (RSP_VAR + VAR_ZSAU) -#define RSP_ZDLE (RSP_VAR + VAR_ZDLE) -#define RSP_ZCTP (RSP_VAR + VAR_ZCTP) -/* - string */ -#define RSP_STR (RSP_VAR + VAR_NUM) -#define RSP_NMBR (RSP_STR + STR_NMBR) -#define RSP_ZCPN (RSP_STR + STR_ZCPN) -#define RSP_ZCON (RSP_STR + STR_ZCON) -#define RSP_ZBC (RSP_STR + STR_ZBC) -#define RSP_ZHLC (RSP_STR + STR_ZHLC) - -#define RSP_WRONG_CID -2 /* unknown cid in cmd */ -#define RSP_INVAL -6 /* invalid response */ -#define RSP_NODEV -9 /* device not connected */ - -#define RSP_NONE -19 -#define RSP_STRING -20 -#define RSP_NULL -21 -#define RSP_INIT -27 -#define RSP_ANY -26 -#define RSP_LAST -28 - -/* actions for process_response */ -#define ACT_NOTHING 0 -#define ACT_SETDLE1 1 -#define ACT_SETDLE0 2 -#define ACT_FAILINIT 3 -#define ACT_HUPMODEM 4 -#define ACT_CONFIGMODE 5 -#define ACT_INIT 6 -#define ACT_DLE0 7 -#define ACT_DLE1 8 -#define ACT_FAILDLE0 9 -#define ACT_FAILDLE1 10 -#define ACT_RING 11 -#define ACT_CID 12 -#define ACT_FAILCID 13 -#define ACT_SDOWN 14 -#define ACT_FAILSDOWN 15 -#define ACT_DEBUG 16 -#define ACT_WARN 17 -#define ACT_DIALING 18 -#define ACT_ABORTDIAL 19 -#define ACT_DISCONNECT 20 -#define ACT_CONNECT 21 -#define ACT_REMOTEREJECT 22 -#define ACT_CONNTIMEOUT 23 -#define ACT_REMOTEHUP 24 -#define ACT_ABORTHUP 25 -#define ACT_ICALL 26 -#define ACT_ACCEPTED 27 -#define ACT_ABORTACCEPT 28 -#define ACT_TIMEOUT 29 -#define ACT_GETSTRING 30 -#define ACT_SETVER 31 -#define ACT_FAILVER 32 -#define ACT_GOTVER 33 -#define ACT_TEST 34 -#define ACT_ERROR 35 -#define ACT_ABORTCID 36 -#define ACT_ZCAU 37 -#define ACT_NOTIFY_BC_DOWN 38 -#define ACT_NOTIFY_BC_UP 39 -#define ACT_DIAL 40 -#define ACT_ACCEPT 41 -#define ACT_HUP 43 -#define ACT_IF_LOCK 44 -#define ACT_START 45 -#define ACT_STOP 46 -#define ACT_FAKEDLE0 47 -#define ACT_FAKEHUP 48 -#define ACT_FAKESDOWN 49 -#define ACT_SHUTDOWN 50 -#define ACT_PROC_CIDMODE 51 -#define ACT_UMODESET 52 -#define ACT_FAILUMODE 53 -#define ACT_CMODESET 54 -#define ACT_FAILCMODE 55 -#define ACT_IF_VER 56 -#define ACT_CMD 100 - -/* at command sequences */ -#define SEQ_NONE 0 -#define SEQ_INIT 100 -#define SEQ_DLE0 200 -#define SEQ_DLE1 250 -#define SEQ_CID 300 -#define SEQ_NOCID 350 -#define SEQ_HUP 400 -#define SEQ_DIAL 600 -#define SEQ_ACCEPT 720 -#define SEQ_SHUTDOWN 500 -#define SEQ_CIDMODE 10 -#define SEQ_UMMODE 11 - - -/* 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), - * 400: hup, 500: reset, 600: dial, 700: ring */ -struct reply_t gigaset_tab_nocid[] = -{ -/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, - * action, command */ - -/* initialize device, set cid mode if possible */ - {RSP_INIT, -1, -1, SEQ_INIT, 100, 1, {ACT_TIMEOUT} }, - - {EV_TIMEOUT, 100, 100, -1, 101, 3, {0}, "Z\r"}, - {RSP_OK, 101, 103, -1, 120, 5, {ACT_GETSTRING}, - "+GMR\r"}, - - {EV_TIMEOUT, 101, 101, -1, 102, 5, {0}, "Z\r"}, - {RSP_ERROR, 101, 101, -1, 102, 5, {0}, "Z\r"}, - - {EV_TIMEOUT, 102, 102, -1, 108, 5, {ACT_SETDLE1}, - "^SDLE=0\r"}, - {RSP_OK, 108, 108, -1, 104, -1}, - {RSP_ZDLE, 104, 104, 0, 103, 5, {0}, "Z\r"}, - {EV_TIMEOUT, 104, 104, -1, 0, 0, {ACT_FAILINIT} }, - {RSP_ERROR, 108, 108, -1, 0, 0, {ACT_FAILINIT} }, - - {EV_TIMEOUT, 108, 108, -1, 105, 2, {ACT_SETDLE0, - ACT_HUPMODEM, - ACT_TIMEOUT} }, - {EV_TIMEOUT, 105, 105, -1, 103, 5, {0}, "Z\r"}, - - {RSP_ERROR, 102, 102, -1, 107, 5, {0}, "^GETPRE\r"}, - {RSP_OK, 107, 107, -1, 0, 0, {ACT_CONFIGMODE} }, - {RSP_ERROR, 107, 107, -1, 0, 0, {ACT_FAILINIT} }, - {EV_TIMEOUT, 107, 107, -1, 0, 0, {ACT_FAILINIT} }, - - {RSP_ERROR, 103, 103, -1, 0, 0, {ACT_FAILINIT} }, - {EV_TIMEOUT, 103, 103, -1, 0, 0, {ACT_FAILINIT} }, - - {RSP_STRING, 120, 120, -1, 121, -1, {ACT_SETVER} }, - - {EV_TIMEOUT, 120, 121, -1, 0, 0, {ACT_FAILVER, - ACT_INIT} }, - {RSP_ERROR, 120, 121, -1, 0, 0, {ACT_FAILVER, - ACT_INIT} }, - {RSP_OK, 121, 121, -1, 0, 0, {ACT_GOTVER, - ACT_INIT} }, - {RSP_NONE, 121, 121, -1, 120, 0, {ACT_GETSTRING} }, - -/* leave dle mode */ - {RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"}, - {RSP_OK, 201, 201, -1, 202, -1}, - {RSP_ZDLE, 202, 202, 0, 0, 0, {ACT_DLE0} }, - {RSP_NODEV, 200, 249, -1, 0, 0, {ACT_FAKEDLE0} }, - {RSP_ERROR, 200, 249, -1, 0, 0, {ACT_FAILDLE0} }, - {EV_TIMEOUT, 200, 249, -1, 0, 0, {ACT_FAILDLE0} }, - -/* enter dle mode */ - {RSP_INIT, 0, 0, SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"}, - {RSP_OK, 251, 251, -1, 252, -1}, - {RSP_ZDLE, 252, 252, 1, 0, 0, {ACT_DLE1} }, - {RSP_ERROR, 250, 299, -1, 0, 0, {ACT_FAILDLE1} }, - {EV_TIMEOUT, 250, 299, -1, 0, 0, {ACT_FAILDLE1} }, - -/* incoming call */ - {RSP_RING, -1, -1, -1, -1, -1, {ACT_RING} }, - -/* get cid */ - {RSP_INIT, 0, 0, SEQ_CID, 301, 5, {0}, "^SGCI?\r"}, - {RSP_OK, 301, 301, -1, 302, -1}, - {RSP_ZGCI, 302, 302, -1, 0, 0, {ACT_CID} }, - {RSP_ERROR, 301, 349, -1, 0, 0, {ACT_FAILCID} }, - {EV_TIMEOUT, 301, 349, -1, 0, 0, {ACT_FAILCID} }, - -/* enter cid mode */ - {RSP_INIT, 0, 0, SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"}, - {RSP_OK, 150, 150, -1, 0, 0, {ACT_CMODESET} }, - {RSP_ERROR, 150, 150, -1, 0, 0, {ACT_FAILCMODE} }, - {EV_TIMEOUT, 150, 150, -1, 0, 0, {ACT_FAILCMODE} }, - -/* leave cid mode */ - {RSP_INIT, 0, 0, SEQ_UMMODE, 160, 5, {0}, "Z\r"}, - {RSP_OK, 160, 160, -1, 0, 0, {ACT_UMODESET} }, - {RSP_ERROR, 160, 160, -1, 0, 0, {ACT_FAILUMODE} }, - {EV_TIMEOUT, 160, 160, -1, 0, 0, {ACT_FAILUMODE} }, - -/* abort getting cid */ - {RSP_INIT, 0, 0, SEQ_NOCID, 0, 0, {ACT_ABORTCID} }, - -/* reset */ - {RSP_INIT, 0, 0, SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"}, - {RSP_OK, 504, 504, -1, 0, 0, {ACT_SDOWN} }, - {RSP_ERROR, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} }, - {EV_TIMEOUT, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} }, - {RSP_NODEV, 501, 599, -1, 0, 0, {ACT_FAKESDOWN} }, - - {EV_PROC_CIDMODE, -1, -1, -1, -1, -1, {ACT_PROC_CIDMODE} }, - {EV_IF_LOCK, -1, -1, -1, -1, -1, {ACT_IF_LOCK} }, - {EV_IF_VER, -1, -1, -1, -1, -1, {ACT_IF_VER} }, - {EV_START, -1, -1, -1, -1, -1, {ACT_START} }, - {EV_STOP, -1, -1, -1, -1, -1, {ACT_STOP} }, - {EV_SHUTDOWN, -1, -1, -1, -1, -1, {ACT_SHUTDOWN} }, - -/* misc. */ - {RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} }, - {RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} }, - {RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} }, - {RSP_LAST} -}; - -/* 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, - * 400: hup, 750: accepted icall */ -struct reply_t gigaset_tab_cid[] = -{ -/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, - * action, command */ - -/* dial */ - {EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} }, - {RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD + AT_BC} }, - {RSP_OK, 601, 601, -1, 603, 5, {ACT_CMD + AT_PROTO} }, - {RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD + AT_TYPE} }, - {RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD + AT_MSN} }, - {RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD + AT_CLIP} }, - {RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD + AT_CLIP} }, - {RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD + AT_ISO} }, - {RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD + AT_ISO} }, - {RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"}, - {RSP_OK, 608, 608, -1, 609, -1}, - {RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD + AT_DIAL} }, - {RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} }, - - {RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, - {EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, - -/* optional dialing responses */ - {EV_BC_OPEN, 650, 650, -1, 651, -1}, - {RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} }, - {RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ZSAU, 650, 651, ZSAU_CALL_DELIVERED, -1, -1, {ACT_DEBUG} }, - -/* connect */ - {RSP_ZSAU, 650, 650, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} }, - {RSP_ZSAU, 651, 651, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT, - ACT_NOTIFY_BC_UP} }, - {RSP_ZSAU, 750, 750, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} }, - {RSP_ZSAU, 751, 751, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT, - ACT_NOTIFY_BC_UP} }, - {EV_BC_OPEN, 800, 800, -1, 800, -1, {ACT_NOTIFY_BC_UP} }, - -/* remote hangup */ - {RSP_ZSAU, 650, 651, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT} }, - {RSP_ZSAU, 750, 751, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} }, - {RSP_ZSAU, 800, 800, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} }, - -/* hangup */ - {EV_HUP, -1, -1, -1, -1, -1, {ACT_HUP} }, - {RSP_INIT, -1, -1, SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, - {RSP_OK, 401, 401, -1, 402, 5}, - {RSP_ZVLS, 402, 402, 0, 403, 5}, - {RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} }, - {RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} }, - {RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} }, - {RSP_ERROR, 401, 401, -1, 0, 0, {ACT_ABORTHUP} }, - {EV_TIMEOUT, 401, 403, -1, 0, 0, {ACT_ABORTHUP} }, - - {EV_BC_CLOSED, 0, 0, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} }, - -/* ring */ - {RSP_ZBC, 700, 700, -1, -1, -1, {0} }, - {RSP_ZHLC, 700, 700, -1, -1, -1, {0} }, - {RSP_NMBR, 700, 700, -1, -1, -1, {0} }, - {RSP_ZCPN, 700, 700, -1, -1, -1, {0} }, - {RSP_ZCTP, 700, 700, -1, -1, -1, {0} }, - {EV_TIMEOUT, 700, 700, -1, 720, 720, {ACT_ICALL} }, - {EV_BC_CLOSED, 720, 720, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} }, - -/*accept icall*/ - {EV_ACCEPT, -1, -1, -1, -1, -1, {ACT_ACCEPT} }, - {RSP_INIT, 720, 720, SEQ_ACCEPT, 721, 5, {ACT_CMD + AT_PROTO} }, - {RSP_OK, 721, 721, -1, 722, 5, {ACT_CMD + AT_ISO} }, - {RSP_OK, 722, 722, -1, 723, 5, {0}, "+VLS=17\r"}, - {RSP_OK, 723, 723, -1, 724, 5, {0} }, - {RSP_ZVLS, 724, 724, 17, 750, 50, {ACT_ACCEPTED} }, - {RSP_ERROR, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} }, - {EV_TIMEOUT, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} }, - {RSP_ZSAU, 700, 729, ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT} }, - {RSP_ZSAU, 700, 729, ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT} }, - {RSP_ZSAU, 700, 729, ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT} }, - - {EV_BC_OPEN, 750, 750, -1, 751, -1}, - {EV_TIMEOUT, 750, 751, -1, 0, 0, {ACT_CONNTIMEOUT} }, - -/* B channel closed (general case) */ - {EV_BC_CLOSED, -1, -1, -1, -1, -1, {ACT_NOTIFY_BC_DOWN} }, - -/* misc. */ - {RSP_ZCON, -1, -1, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} }, - {RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} }, - {RSP_LAST} -}; - - -static const struct resp_type_t { - char *response; - int resp_code; - int type; -} -resp_type[] = -{ - {"OK", RSP_OK, RT_NOTHING}, - {"ERROR", RSP_ERROR, RT_NOTHING}, - {"ZSAU", RSP_ZSAU, RT_ZSAU}, - {"ZCAU", RSP_ZCAU, RT_ZCAU}, - {"RING", RSP_RING, RT_RING}, - {"ZGCI", RSP_ZGCI, RT_NUMBER}, - {"ZVLS", RSP_ZVLS, RT_NUMBER}, - {"ZCTP", RSP_ZCTP, RT_NUMBER}, - {"ZDLE", RSP_ZDLE, RT_NUMBER}, - {"ZHLC", RSP_ZHLC, RT_STRING}, - {"ZBC", RSP_ZBC, RT_STRING}, - {"NMBR", RSP_NMBR, RT_STRING}, - {"ZCPN", RSP_ZCPN, RT_STRING}, - {"ZCON", RSP_ZCON, RT_STRING}, - {NULL, 0, 0} -}; - -static const struct zsau_resp_t { - char *str; - int code; -} -zsau_resp[] = -{ - {"OUTGOING_CALL_PROCEEDING", ZSAU_PROCEEDING}, - {"CALL_DELIVERED", ZSAU_CALL_DELIVERED}, - {"ACTIVE", ZSAU_ACTIVE}, - {"DISCONNECT_IND", ZSAU_DISCONNECT_IND}, - {"NULL", ZSAU_NULL}, - {"DISCONNECT_REQ", ZSAU_DISCONNECT_REQ}, - {NULL, ZSAU_UNKNOWN} -}; - -/* check for and remove fixed string prefix - * If s starts with prefix terminated by a non-alphanumeric character, - * return pointer to the first character after that, otherwise return NULL. - */ -static char *skip_prefix(char *s, const char *prefix) -{ - while (*prefix) - if (*s++ != *prefix++) - return NULL; - if (isalnum(*s)) - return NULL; - return s; -} - -/* queue event with CID */ -static void add_cid_event(struct cardstate *cs, int cid, int type, - void *ptr, int parameter) -{ - unsigned long flags; - unsigned next, tail; - struct event_t *event; - - gig_dbg(DEBUG_EVENT, "queueing event %d for cid %d", type, cid); - - spin_lock_irqsave(&cs->ev_lock, flags); - - tail = cs->ev_tail; - next = (tail + 1) % MAX_EVENTS; - if (unlikely(next == cs->ev_head)) { - dev_err(cs->dev, "event queue full\n"); - kfree(ptr); - } else { - event = cs->events + tail; - event->type = type; - event->cid = cid; - event->ptr = ptr; - event->arg = NULL; - event->parameter = parameter; - event->at_state = NULL; - cs->ev_tail = next; - } - - spin_unlock_irqrestore(&cs->ev_lock, flags); -} - -/** - * gigaset_handle_modem_response() - process received modem response - * @cs: device descriptor structure. - * - * Called by asyncdata/isocdata if a block of data received from the - * device must be processed as a modem command response. The data is - * already in the cs structure. - */ -void gigaset_handle_modem_response(struct cardstate *cs) -{ - char *eoc, *psep, *ptr; - const struct resp_type_t *rt; - const struct zsau_resp_t *zr; - int cid, parameter; - u8 type, value; - - if (!cs->cbytes) { - /* ignore additional LFs/CRs (M10x config mode or cx100) */ - gig_dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[0]); - return; - } - cs->respdata[cs->cbytes] = 0; - - if (cs->at_state.getstring) { - /* state machine wants next line verbatim */ - cs->at_state.getstring = 0; - ptr = kstrdup(cs->respdata, GFP_ATOMIC); - gig_dbg(DEBUG_EVENT, "string==%s", ptr ? ptr : "NULL"); - add_cid_event(cs, 0, RSP_STRING, ptr, 0); - return; - } - - /* look up response type */ - for (rt = resp_type; rt->response; ++rt) { - eoc = skip_prefix(cs->respdata, rt->response); - if (eoc) - break; - } - if (!rt->response) { - add_cid_event(cs, 0, RSP_NONE, NULL, 0); - gig_dbg(DEBUG_EVENT, "unknown modem response: '%s'\n", - cs->respdata); - return; - } - - /* check for CID */ - psep = strrchr(cs->respdata, ';'); - if (psep && - !kstrtoint(psep + 1, 10, &cid) && - cid >= 1 && cid <= 65535) { - /* valid CID: chop it off */ - *psep = 0; - } else { - /* no valid CID: leave unchanged */ - cid = 0; - } - - gig_dbg(DEBUG_EVENT, "CMD received: %s", cs->respdata); - if (cid) - gig_dbg(DEBUG_EVENT, "CID: %d", cid); - - switch (rt->type) { - case RT_NOTHING: - /* check parameter separator */ - if (*eoc) - goto bad_param; /* extra parameter */ - - add_cid_event(cs, cid, rt->resp_code, NULL, 0); - break; - - case RT_RING: - /* check parameter separator */ - if (!*eoc) - eoc = NULL; /* no parameter */ - else if (*eoc++ != ',') - goto bad_param; - - add_cid_event(cs, 0, rt->resp_code, NULL, cid); - - /* process parameters as individual responses */ - while (eoc) { - /* look up parameter type */ - psep = NULL; - for (rt = resp_type; rt->response; ++rt) { - psep = skip_prefix(eoc, rt->response); - if (psep) - break; - } - - /* all legal parameters are of type RT_STRING */ - if (!psep || rt->type != RT_STRING) { - dev_warn(cs->dev, - "illegal RING parameter: '%s'\n", - eoc); - return; - } - - /* skip parameter value separator */ - if (*psep++ != '=') - goto bad_param; - - /* look up end of parameter */ - eoc = strchr(psep, ','); - if (eoc) - *eoc++ = 0; - - /* retrieve parameter value */ - ptr = kstrdup(psep, GFP_ATOMIC); - - /* queue event */ - add_cid_event(cs, cid, rt->resp_code, ptr, 0); - } - break; - - case RT_ZSAU: - /* check parameter separator */ - if (!*eoc) { - /* no parameter */ - add_cid_event(cs, cid, rt->resp_code, NULL, ZSAU_NONE); - break; - } - if (*eoc++ != '=') - goto bad_param; - - /* look up parameter value */ - for (zr = zsau_resp; zr->str; ++zr) - if (!strcmp(eoc, zr->str)) - break; - if (!zr->str) - goto bad_param; - - add_cid_event(cs, cid, rt->resp_code, NULL, zr->code); - break; - - case RT_STRING: - /* check parameter separator */ - if (*eoc++ != '=') - goto bad_param; - - /* retrieve parameter value */ - ptr = kstrdup(eoc, GFP_ATOMIC); - - /* queue event */ - add_cid_event(cs, cid, rt->resp_code, ptr, 0); - break; - - case RT_ZCAU: - /* check parameter separators */ - if (*eoc++ != '=') - goto bad_param; - psep = strchr(eoc, ','); - if (!psep) - goto bad_param; - *psep++ = 0; - - /* decode parameter values */ - if (kstrtou8(eoc, 16, &type) || kstrtou8(psep, 16, &value)) { - *--psep = ','; - goto bad_param; - } - parameter = (type << 8) | value; - - add_cid_event(cs, cid, rt->resp_code, NULL, parameter); - break; - - case RT_NUMBER: - /* check parameter separator */ - if (*eoc++ != '=') - goto bad_param; - - /* decode parameter value */ - if (kstrtoint(eoc, 10, ¶meter)) - goto bad_param; - - /* special case ZDLE: set flag before queueing event */ - if (rt->resp_code == RSP_ZDLE) - cs->dle = parameter; - - add_cid_event(cs, cid, rt->resp_code, NULL, parameter); - break; - -bad_param: - /* parameter unexpected, incomplete or malformed */ - dev_warn(cs->dev, "bad parameter in response '%s'\n", - cs->respdata); - add_cid_event(cs, cid, rt->resp_code, NULL, -1); - break; - - default: - dev_err(cs->dev, "%s: internal error on '%s'\n", - __func__, cs->respdata); - } -} -EXPORT_SYMBOL_GPL(gigaset_handle_modem_response); - -/* disconnect_nobc - * process closing of connection associated with given AT state structure - * without B channel - */ -static void disconnect_nobc(struct at_state_t **at_state_p, - struct cardstate *cs) -{ - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - ++(*at_state_p)->seq_index; - - /* revert to selected idle mode */ - if (!cs->cidmode) { - cs->at_state.pending_commands |= PC_UMMODE; - gig_dbg(DEBUG_EVENT, "Scheduling PC_UMMODE"); - cs->commands_pending = 1; - } - - /* check for and deallocate temporary AT state */ - if (!list_empty(&(*at_state_p)->list)) { - list_del(&(*at_state_p)->list); - kfree(*at_state_p); - *at_state_p = NULL; - } - - spin_unlock_irqrestore(&cs->lock, flags); -} - -/* disconnect_bc - * process closing of connection associated with given AT state structure - * and B channel - */ -static void disconnect_bc(struct at_state_t *at_state, - struct cardstate *cs, struct bc_state *bcs) -{ - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - ++at_state->seq_index; - - /* revert to selected idle mode */ - if (!cs->cidmode) { - cs->at_state.pending_commands |= PC_UMMODE; - gig_dbg(DEBUG_EVENT, "Scheduling PC_UMMODE"); - cs->commands_pending = 1; - } - spin_unlock_irqrestore(&cs->lock, flags); - - /* invoke hardware specific handler */ - cs->ops->close_bchannel(bcs); - - /* notify LL */ - if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { - bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); - gigaset_isdn_hupD(bcs); - } -} - -/* get_free_channel - * get a free AT state structure: either one of those associated with the - * B channels of the Gigaset device, or if none of those is available, - * a newly allocated one with bcs=NULL - * The structure should be freed by calling disconnect_nobc() after use. - */ -static inline struct at_state_t *get_free_channel(struct cardstate *cs, - int cid) -/* cids: >0: siemens-cid - * 0: without cid - * -1: no cid assigned yet - */ -{ - unsigned long flags; - int i; - struct at_state_t *ret; - - for (i = 0; i < cs->channels; ++i) - if (gigaset_get_channel(cs->bcs + i) >= 0) { - ret = &cs->bcs[i].at_state; - ret->cid = cid; - return ret; - } - - spin_lock_irqsave(&cs->lock, flags); - ret = kmalloc(sizeof(struct at_state_t), GFP_ATOMIC); - if (ret) { - gigaset_at_init(ret, NULL, cs, cid); - list_add(&ret->list, &cs->temp_at_states); - } - spin_unlock_irqrestore(&cs->lock, flags); - return ret; -} - -static void init_failed(struct cardstate *cs, int mode) -{ - int i; - struct at_state_t *at_state; - - cs->at_state.pending_commands &= ~PC_INIT; - cs->mode = mode; - cs->mstate = MS_UNINITIALIZED; - gigaset_free_channels(cs); - for (i = 0; i < cs->channels; ++i) { - at_state = &cs->bcs[i].at_state; - if (at_state->pending_commands & PC_CID) { - at_state->pending_commands &= ~PC_CID; - at_state->pending_commands |= PC_NOCID; - cs->commands_pending = 1; - } - } -} - -static void schedule_init(struct cardstate *cs, int state) -{ - if (cs->at_state.pending_commands & PC_INIT) { - gig_dbg(DEBUG_EVENT, "not scheduling PC_INIT again"); - return; - } - cs->mstate = state; - cs->mode = M_UNKNOWN; - gigaset_block_channels(cs); - cs->at_state.pending_commands |= PC_INIT; - gig_dbg(DEBUG_EVENT, "Scheduling PC_INIT"); - cs->commands_pending = 1; -} - -/* send an AT command - * adding the "AT" prefix, cid and DLE encapsulation as appropriate - */ -static void send_command(struct cardstate *cs, const char *cmd, - struct at_state_t *at_state) -{ - int cid = at_state->cid; - struct cmdbuf_t *cb; - size_t buflen; - - buflen = strlen(cmd) + 12; /* DLE ( A T 1 2 3 4 5 DLE ) \0 */ - cb = kmalloc(sizeof(struct cmdbuf_t) + buflen, GFP_ATOMIC); - if (!cb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - if (cid > 0 && cid <= 65535) - cb->len = snprintf(cb->buf, buflen, - cs->dle ? "\020(AT%d%s\020)" : "AT%d%s", - cid, cmd); - else - cb->len = snprintf(cb->buf, buflen, - cs->dle ? "\020(AT%s\020)" : "AT%s", - cmd); - cb->offset = 0; - cb->next = NULL; - cb->wake_tasklet = NULL; - cs->ops->write_cmd(cs, cb); -} - -static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid) -{ - struct at_state_t *at_state; - int i; - unsigned long flags; - - if (cid == 0) - return &cs->at_state; - - for (i = 0; i < cs->channels; ++i) - if (cid == cs->bcs[i].at_state.cid) - return &cs->bcs[i].at_state; - - spin_lock_irqsave(&cs->lock, flags); - - list_for_each_entry(at_state, &cs->temp_at_states, list) - if (cid == at_state->cid) { - spin_unlock_irqrestore(&cs->lock, flags); - return at_state; - } - - spin_unlock_irqrestore(&cs->lock, flags); - - return NULL; -} - -static void bchannel_down(struct bc_state *bcs) -{ - if (bcs->chstate & CHS_B_UP) { - bcs->chstate &= ~CHS_B_UP; - gigaset_isdn_hupB(bcs); - } - - if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { - bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); - gigaset_isdn_hupD(bcs); - } - - gigaset_free_channel(bcs); - - gigaset_bcs_reinit(bcs); -} - -static void bchannel_up(struct bc_state *bcs) -{ - if (bcs->chstate & CHS_B_UP) { - dev_notice(bcs->cs->dev, "%s: B channel already up\n", - __func__); - return; - } - - bcs->chstate |= CHS_B_UP; - gigaset_isdn_connB(bcs); -} - -static void start_dial(struct at_state_t *at_state, void *data, - unsigned seq_index) -{ - struct bc_state *bcs = at_state->bcs; - struct cardstate *cs = at_state->cs; - char **commands = data; - unsigned long flags; - int i; - - bcs->chstate |= CHS_NOTIFY_LL; - - spin_lock_irqsave(&cs->lock, flags); - if (at_state->seq_index != seq_index) { - spin_unlock_irqrestore(&cs->lock, flags); - goto error; - } - spin_unlock_irqrestore(&cs->lock, flags); - - for (i = 0; i < AT_NUM; ++i) { - kfree(bcs->commands[i]); - bcs->commands[i] = commands[i]; - } - - at_state->pending_commands |= PC_CID; - gig_dbg(DEBUG_EVENT, "Scheduling PC_CID"); - cs->commands_pending = 1; - return; - -error: - for (i = 0; i < AT_NUM; ++i) { - kfree(commands[i]); - commands[i] = NULL; - } - at_state->pending_commands |= PC_NOCID; - gig_dbg(DEBUG_EVENT, "Scheduling PC_NOCID"); - cs->commands_pending = 1; - return; -} - -static void start_accept(struct at_state_t *at_state) -{ - struct cardstate *cs = at_state->cs; - struct bc_state *bcs = at_state->bcs; - int i; - - for (i = 0; i < AT_NUM; ++i) { - kfree(bcs->commands[i]); - bcs->commands[i] = NULL; - } - - bcs->commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC); - bcs->commands[AT_ISO] = kmalloc(9, GFP_ATOMIC); - if (!bcs->commands[AT_PROTO] || !bcs->commands[AT_ISO]) { - dev_err(at_state->cs->dev, "out of memory\n"); - /* error reset */ - at_state->pending_commands |= PC_HUP; - gig_dbg(DEBUG_EVENT, "Scheduling PC_HUP"); - cs->commands_pending = 1; - return; - } - - snprintf(bcs->commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); - snprintf(bcs->commands[AT_ISO], 9, "^SISO=%u\r", bcs->channel + 1); - - at_state->pending_commands |= PC_ACCEPT; - gig_dbg(DEBUG_EVENT, "Scheduling PC_ACCEPT"); - cs->commands_pending = 1; -} - -static void do_start(struct cardstate *cs) -{ - gigaset_free_channels(cs); - - if (cs->mstate != MS_LOCKED) - schedule_init(cs, MS_INIT); - - cs->isdn_up = 1; - gigaset_isdn_start(cs); - - cs->waiting = 0; - wake_up(&cs->waitqueue); -} - -static void finish_shutdown(struct cardstate *cs) -{ - if (cs->mstate != MS_LOCKED) { - cs->mstate = MS_UNINITIALIZED; - cs->mode = M_UNKNOWN; - } - - /* Tell the LL that the device is not available .. */ - if (cs->isdn_up) { - cs->isdn_up = 0; - gigaset_isdn_stop(cs); - } - - /* The rest is done by cleanup_cs() in process context. */ - - cs->cmd_result = -ENODEV; - cs->waiting = 0; - wake_up(&cs->waitqueue); -} - -static void do_shutdown(struct cardstate *cs) -{ - gigaset_block_channels(cs); - - if (cs->mstate == MS_READY) { - cs->mstate = MS_SHUTDOWN; - cs->at_state.pending_commands |= PC_SHUTDOWN; - gig_dbg(DEBUG_EVENT, "Scheduling PC_SHUTDOWN"); - cs->commands_pending = 1; - } else - finish_shutdown(cs); -} - -static void do_stop(struct cardstate *cs) -{ - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - cs->connected = 0; - spin_unlock_irqrestore(&cs->lock, flags); - - do_shutdown(cs); -} - -/* Entering cid mode or getting a cid failed: - * try to initialize the device and try again. - * - * channel >= 0: getting cid for the channel failed - * channel < 0: entering cid mode failed - * - * returns 0 on success, <0 on failure - */ -static int reinit_and_retry(struct cardstate *cs, int channel) -{ - int i; - - if (--cs->retry_count <= 0) - return -EFAULT; - - for (i = 0; i < cs->channels; ++i) - if (cs->bcs[i].at_state.cid > 0) - return -EBUSY; - - if (channel < 0) - dev_warn(cs->dev, - "Could not enter cid mode. Reinit device and try again.\n"); - else { - dev_warn(cs->dev, - "Could not get a call id. Reinit device and try again.\n"); - cs->bcs[channel].at_state.pending_commands |= PC_CID; - } - schedule_init(cs, MS_INIT); - return 0; -} - -static int at_state_invalid(struct cardstate *cs, - struct at_state_t *test_ptr) -{ - unsigned long flags; - unsigned channel; - struct at_state_t *at_state; - int retval = 0; - - spin_lock_irqsave(&cs->lock, flags); - - if (test_ptr == &cs->at_state) - goto exit; - - list_for_each_entry(at_state, &cs->temp_at_states, list) - if (at_state == test_ptr) - goto exit; - - for (channel = 0; channel < cs->channels; ++channel) - if (&cs->bcs[channel].at_state == test_ptr) - goto exit; - - retval = 1; -exit: - spin_unlock_irqrestore(&cs->lock, flags); - return retval; -} - -static void handle_icall(struct cardstate *cs, struct bc_state *bcs, - struct at_state_t *at_state) -{ - int retval; - - retval = gigaset_isdn_icall(at_state); - switch (retval) { - case ICALL_ACCEPT: - break; - default: - dev_err(cs->dev, "internal error: disposition=%d\n", retval); - /* fall through */ - case ICALL_IGNORE: - case ICALL_REJECT: - /* hang up actively - * Device doc says that would reject the call. - * In fact it doesn't. - */ - at_state->pending_commands |= PC_HUP; - cs->commands_pending = 1; - break; - } -} - -static int do_lock(struct cardstate *cs) -{ - int mode; - int i; - - switch (cs->mstate) { - case MS_UNINITIALIZED: - case MS_READY: - if (cs->cur_at_seq || !list_empty(&cs->temp_at_states) || - cs->at_state.pending_commands) - return -EBUSY; - - for (i = 0; i < cs->channels; ++i) - if (cs->bcs[i].at_state.pending_commands) - return -EBUSY; - - if (gigaset_get_channels(cs) < 0) - return -EBUSY; - - break; - case MS_LOCKED: - break; - default: - return -EBUSY; - } - - mode = cs->mode; - cs->mstate = MS_LOCKED; - cs->mode = M_UNKNOWN; - - return mode; -} - -static int do_unlock(struct cardstate *cs) -{ - if (cs->mstate != MS_LOCKED) - return -EINVAL; - - cs->mstate = MS_UNINITIALIZED; - cs->mode = M_UNKNOWN; - gigaset_free_channels(cs); - if (cs->connected) - schedule_init(cs, MS_INIT); - - return 0; -} - -static void do_action(int action, struct cardstate *cs, - struct bc_state *bcs, - struct at_state_t **p_at_state, char **pp_command, - int *p_genresp, int *p_resp_code, - struct event_t *ev) -{ - struct at_state_t *at_state = *p_at_state; - struct bc_state *bcs2; - unsigned long flags; - - int channel; - - unsigned char *s, *e; - int i; - unsigned long val; - - switch (action) { - case ACT_NOTHING: - break; - case ACT_TIMEOUT: - at_state->waiting = 1; - break; - case ACT_INIT: - cs->at_state.pending_commands &= ~PC_INIT; - cs->cur_at_seq = SEQ_NONE; - cs->mode = M_UNIMODEM; - spin_lock_irqsave(&cs->lock, flags); - if (!cs->cidmode) { - spin_unlock_irqrestore(&cs->lock, flags); - gigaset_free_channels(cs); - cs->mstate = MS_READY; - break; - } - spin_unlock_irqrestore(&cs->lock, flags); - cs->at_state.pending_commands |= PC_CIDMODE; - gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); - cs->commands_pending = 1; - break; - case ACT_FAILINIT: - dev_warn(cs->dev, "Could not initialize the device.\n"); - cs->dle = 0; - init_failed(cs, M_UNKNOWN); - cs->cur_at_seq = SEQ_NONE; - break; - case ACT_CONFIGMODE: - init_failed(cs, M_CONFIG); - cs->cur_at_seq = SEQ_NONE; - break; - case ACT_SETDLE1: - cs->dle = 1; - /* cs->inbuf[0].inputstate |= INS_command | INS_DLE_command; */ - cs->inbuf[0].inputstate &= - ~(INS_command | INS_DLE_command); - break; - case ACT_SETDLE0: - cs->dle = 0; - cs->inbuf[0].inputstate = - (cs->inbuf[0].inputstate & ~INS_DLE_command) - | INS_command; - break; - case ACT_CMODESET: - if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) { - gigaset_free_channels(cs); - cs->mstate = MS_READY; - } - cs->mode = M_CID; - cs->cur_at_seq = SEQ_NONE; - break; - case ACT_UMODESET: - cs->mode = M_UNIMODEM; - cs->cur_at_seq = SEQ_NONE; - break; - case ACT_FAILCMODE: - cs->cur_at_seq = SEQ_NONE; - if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) { - init_failed(cs, M_UNKNOWN); - break; - } - if (reinit_and_retry(cs, -1) < 0) - schedule_init(cs, MS_RECOVER); - break; - case ACT_FAILUMODE: - cs->cur_at_seq = SEQ_NONE; - schedule_init(cs, MS_RECOVER); - break; - case ACT_HUPMODEM: - /* send "+++" (hangup in unimodem mode) */ - if (cs->connected) { - struct cmdbuf_t *cb; - - cb = kmalloc(sizeof(struct cmdbuf_t) + 3, GFP_ATOMIC); - if (!cb) { - dev_err(cs->dev, "%s: out of memory\n", - __func__); - return; - } - memcpy(cb->buf, "+++", 3); - cb->len = 3; - cb->offset = 0; - cb->next = NULL; - cb->wake_tasklet = NULL; - cs->ops->write_cmd(cs, cb); - } - break; - case ACT_RING: - /* get fresh AT state structure for new CID */ - at_state = get_free_channel(cs, ev->parameter); - if (!at_state) { - dev_warn(cs->dev, - "RING ignored: could not allocate channel structure\n"); - break; - } - - /* initialize AT state structure - * note that bcs may be NULL if no B channel is free - */ - at_state->ConState = 700; - for (i = 0; i < STR_NUM; ++i) { - kfree(at_state->str_var[i]); - at_state->str_var[i] = NULL; - } - at_state->int_var[VAR_ZCTP] = -1; - - spin_lock_irqsave(&cs->lock, flags); - at_state->timer_expires = RING_TIMEOUT; - at_state->timer_active = 1; - spin_unlock_irqrestore(&cs->lock, flags); - break; - case ACT_ICALL: - handle_icall(cs, bcs, at_state); - break; - case ACT_FAILSDOWN: - dev_warn(cs->dev, "Could not shut down the device.\n"); - /* fall through */ - case ACT_FAKESDOWN: - case ACT_SDOWN: - cs->cur_at_seq = SEQ_NONE; - finish_shutdown(cs); - break; - case ACT_CONNECT: - if (cs->onechannel) { - at_state->pending_commands |= PC_DLE1; - cs->commands_pending = 1; - break; - } - bcs->chstate |= CHS_D_UP; - gigaset_isdn_connD(bcs); - cs->ops->init_bchannel(bcs); - break; - case ACT_DLE1: - cs->cur_at_seq = SEQ_NONE; - bcs = cs->bcs + cs->curchannel; - - bcs->chstate |= CHS_D_UP; - gigaset_isdn_connD(bcs); - cs->ops->init_bchannel(bcs); - break; - case ACT_FAKEHUP: - at_state->int_var[VAR_ZSAU] = ZSAU_NULL; - /* fall through */ - case ACT_DISCONNECT: - cs->cur_at_seq = SEQ_NONE; - at_state->cid = -1; - if (!bcs) { - disconnect_nobc(p_at_state, cs); - } else if (cs->onechannel && cs->dle) { - /* Check for other open channels not needed: - * DLE only used for M10x with one B channel. - */ - at_state->pending_commands |= PC_DLE0; - cs->commands_pending = 1; - } else { - disconnect_bc(at_state, cs, bcs); - } - break; - case ACT_FAKEDLE0: - at_state->int_var[VAR_ZDLE] = 0; - cs->dle = 0; - /* fall through */ - case ACT_DLE0: - cs->cur_at_seq = SEQ_NONE; - bcs2 = cs->bcs + cs->curchannel; - disconnect_bc(&bcs2->at_state, cs, bcs2); - break; - case ACT_ABORTHUP: - cs->cur_at_seq = SEQ_NONE; - dev_warn(cs->dev, "Could not hang up.\n"); - at_state->cid = -1; - if (!bcs) - disconnect_nobc(p_at_state, cs); - else if (cs->onechannel) - at_state->pending_commands |= PC_DLE0; - else - disconnect_bc(at_state, cs, bcs); - schedule_init(cs, MS_RECOVER); - break; - case ACT_FAILDLE0: - cs->cur_at_seq = SEQ_NONE; - dev_warn(cs->dev, "Error leaving DLE mode.\n"); - cs->dle = 0; - bcs2 = cs->bcs + cs->curchannel; - disconnect_bc(&bcs2->at_state, cs, bcs2); - schedule_init(cs, MS_RECOVER); - break; - case ACT_FAILDLE1: - cs->cur_at_seq = SEQ_NONE; - dev_warn(cs->dev, - "Could not enter DLE mode. Trying to hang up.\n"); - channel = cs->curchannel; - cs->bcs[channel].at_state.pending_commands |= PC_HUP; - cs->commands_pending = 1; - break; - - case ACT_CID: /* got cid; start dialing */ - cs->cur_at_seq = SEQ_NONE; - channel = cs->curchannel; - if (ev->parameter > 0 && ev->parameter <= 65535) { - cs->bcs[channel].at_state.cid = ev->parameter; - cs->bcs[channel].at_state.pending_commands |= - PC_DIAL; - cs->commands_pending = 1; - break; - } - /* fall through - bad cid */ - case ACT_FAILCID: - cs->cur_at_seq = SEQ_NONE; - channel = cs->curchannel; - if (reinit_and_retry(cs, channel) < 0) { - dev_warn(cs->dev, - "Could not get a call ID. Cannot dial.\n"); - bcs2 = cs->bcs + channel; - disconnect_bc(&bcs2->at_state, cs, bcs2); - } - break; - case ACT_ABORTCID: - cs->cur_at_seq = SEQ_NONE; - bcs2 = cs->bcs + cs->curchannel; - disconnect_bc(&bcs2->at_state, cs, bcs2); - break; - - case ACT_DIALING: - case ACT_ACCEPTED: - cs->cur_at_seq = SEQ_NONE; - break; - - case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL procssng */ - if (bcs) - disconnect_bc(at_state, cs, bcs); - else - disconnect_nobc(p_at_state, cs); - break; - - case ACT_ABORTDIAL: /* error/timeout during dial preparation */ - cs->cur_at_seq = SEQ_NONE; - at_state->pending_commands |= PC_HUP; - cs->commands_pending = 1; - break; - - case ACT_REMOTEREJECT: /* DISCONNECT_IND after dialling */ - case ACT_CONNTIMEOUT: /* timeout waiting for ZSAU=ACTIVE */ - case ACT_REMOTEHUP: /* DISCONNECT_IND with established connection */ - at_state->pending_commands |= PC_HUP; - cs->commands_pending = 1; - break; - case ACT_GETSTRING: /* warning: RING, ZDLE, ... - are not handled properly anymore */ - at_state->getstring = 1; - break; - case ACT_SETVER: - if (!ev->ptr) { - *p_genresp = 1; - *p_resp_code = RSP_ERROR; - break; - } - s = ev->ptr; - - if (!strcmp(s, "OK")) { - /* OK without version string: assume old response */ - *p_genresp = 1; - *p_resp_code = RSP_NONE; - break; - } - - for (i = 0; i < 4; ++i) { - val = simple_strtoul(s, (char **) &e, 10); - if (val > INT_MAX || e == s) - break; - if (i == 3) { - if (*e) - break; - } else if (*e != '.') - break; - else - s = e + 1; - cs->fwver[i] = val; - } - if (i != 4) { - *p_genresp = 1; - *p_resp_code = RSP_ERROR; - break; - } - cs->gotfwver = 0; - break; - case ACT_GOTVER: - if (cs->gotfwver == 0) { - cs->gotfwver = 1; - gig_dbg(DEBUG_EVENT, - "firmware version %02d.%03d.%02d.%02d", - cs->fwver[0], cs->fwver[1], - cs->fwver[2], cs->fwver[3]); - break; - } - /* fall through */ - case ACT_FAILVER: - cs->gotfwver = -1; - dev_err(cs->dev, "could not read firmware version.\n"); - break; - case ACT_ERROR: - gig_dbg(DEBUG_ANY, "%s: ERROR response in ConState %d", - __func__, at_state->ConState); - cs->cur_at_seq = SEQ_NONE; - break; - case ACT_DEBUG: - gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", - __func__, ev->type, at_state->ConState); - break; - case ACT_WARN: - dev_warn(cs->dev, "%s: resp_code %d in ConState %d!\n", - __func__, ev->type, at_state->ConState); - break; - case ACT_ZCAU: - dev_warn(cs->dev, "cause code %04x in connection state %d.\n", - ev->parameter, at_state->ConState); - break; - - /* events from the LL */ - - case ACT_DIAL: - if (!ev->ptr) { - *p_genresp = 1; - *p_resp_code = RSP_ERROR; - break; - } - start_dial(at_state, ev->ptr, ev->parameter); - break; - case ACT_ACCEPT: - start_accept(at_state); - break; - case ACT_HUP: - at_state->pending_commands |= PC_HUP; - gig_dbg(DEBUG_EVENT, "Scheduling PC_HUP"); - cs->commands_pending = 1; - break; - - /* hotplug events */ - - case ACT_STOP: - do_stop(cs); - break; - case ACT_START: - do_start(cs); - break; - - /* events from the interface */ - - case ACT_IF_LOCK: - cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs); - cs->waiting = 0; - wake_up(&cs->waitqueue); - break; - case ACT_IF_VER: - if (ev->parameter != 0) - cs->cmd_result = -EINVAL; - else if (cs->gotfwver != 1) { - cs->cmd_result = -ENOENT; - } else { - memcpy(ev->arg, cs->fwver, sizeof cs->fwver); - cs->cmd_result = 0; - } - cs->waiting = 0; - wake_up(&cs->waitqueue); - break; - - /* events from the proc file system */ - - case ACT_PROC_CIDMODE: - spin_lock_irqsave(&cs->lock, flags); - if (ev->parameter != cs->cidmode) { - cs->cidmode = ev->parameter; - if (ev->parameter) { - cs->at_state.pending_commands |= PC_CIDMODE; - gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); - } else { - cs->at_state.pending_commands |= PC_UMMODE; - gig_dbg(DEBUG_EVENT, "Scheduling PC_UMMODE"); - } - cs->commands_pending = 1; - } - spin_unlock_irqrestore(&cs->lock, flags); - cs->waiting = 0; - wake_up(&cs->waitqueue); - break; - - /* events from the hardware drivers */ - - case ACT_NOTIFY_BC_DOWN: - bchannel_down(bcs); - break; - case ACT_NOTIFY_BC_UP: - bchannel_up(bcs); - break; - case ACT_SHUTDOWN: - do_shutdown(cs); - break; - - - default: - if (action >= ACT_CMD && action < ACT_CMD + AT_NUM) { - *pp_command = at_state->bcs->commands[action - ACT_CMD]; - if (!*pp_command) { - *p_genresp = 1; - *p_resp_code = RSP_NULL; - } - } else - dev_err(cs->dev, "%s: action==%d!\n", __func__, action); - } -} - -/* State machine to do the calling and hangup procedure */ -static void process_event(struct cardstate *cs, struct event_t *ev) -{ - struct bc_state *bcs; - char *p_command = NULL; - struct reply_t *rep; - int rcode; - int genresp = 0; - int resp_code = RSP_ERROR; - struct at_state_t *at_state; - int index; - int curact; - unsigned long flags; - - if (ev->cid >= 0) { - at_state = at_state_from_cid(cs, ev->cid); - if (!at_state) { - gig_dbg(DEBUG_EVENT, "event %d for invalid cid %d", - ev->type, ev->cid); - gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID, - NULL, 0, NULL); - return; - } - } else { - at_state = ev->at_state; - if (at_state_invalid(cs, at_state)) { - gig_dbg(DEBUG_EVENT, "event for invalid at_state %p", - at_state); - return; - } - } - - gig_dbg(DEBUG_EVENT, "connection state %d, event %d", - at_state->ConState, ev->type); - - bcs = at_state->bcs; - - /* Setting the pointer to the dial array */ - rep = at_state->replystruct; - - spin_lock_irqsave(&cs->lock, flags); - if (ev->type == EV_TIMEOUT) { - if (ev->parameter != at_state->timer_index - || !at_state->timer_active) { - ev->type = RSP_NONE; /* old timeout */ - gig_dbg(DEBUG_EVENT, "old timeout"); - } else { - if (at_state->waiting) - gig_dbg(DEBUG_EVENT, "stopped waiting"); - else - gig_dbg(DEBUG_EVENT, "timeout occurred"); - } - } - spin_unlock_irqrestore(&cs->lock, flags); - - /* if the response belongs to a variable in at_state->int_var[VAR_XXXX] - or at_state->str_var[STR_XXXX], set it */ - if (ev->type >= RSP_VAR && ev->type < RSP_VAR + VAR_NUM) { - index = ev->type - RSP_VAR; - at_state->int_var[index] = ev->parameter; - } else if (ev->type >= RSP_STR && ev->type < RSP_STR + STR_NUM) { - index = ev->type - RSP_STR; - kfree(at_state->str_var[index]); - at_state->str_var[index] = ev->ptr; - ev->ptr = NULL; /* prevent process_events() from - deallocating ptr */ - } - - if (ev->type == EV_TIMEOUT || ev->type == RSP_STRING) - at_state->getstring = 0; - - /* Search row in dial array which matches modem response and current - constate */ - for (;; rep++) { - rcode = rep->resp_code; - if (rcode == RSP_LAST) { - /* found nothing...*/ - dev_warn(cs->dev, "%s: rcode=RSP_LAST: " - "resp_code %d in ConState %d!\n", - __func__, ev->type, at_state->ConState); - return; - } - if ((rcode == RSP_ANY || rcode == ev->type) - && ((int) at_state->ConState >= rep->min_ConState) - && (rep->max_ConState < 0 - || (int) at_state->ConState <= rep->max_ConState) - && (rep->parameter < 0 || rep->parameter == ev->parameter)) - break; - } - - p_command = rep->command; - - at_state->waiting = 0; - for (curact = 0; curact < MAXACT; ++curact) { - /* The row tells us what we should do .. - */ - do_action(rep->action[curact], cs, bcs, &at_state, &p_command, - &genresp, &resp_code, ev); - if (!at_state) - /* at_state destroyed by disconnect */ - return; - } - - /* Jump to the next con-state regarding the array */ - if (rep->new_ConState >= 0) - at_state->ConState = rep->new_ConState; - - if (genresp) { - spin_lock_irqsave(&cs->lock, flags); - at_state->timer_expires = 0; - at_state->timer_active = 0; - spin_unlock_irqrestore(&cs->lock, flags); - gigaset_add_event(cs, at_state, resp_code, NULL, 0, NULL); - } else { - /* Send command to modem if not NULL... */ - if (p_command) { - if (cs->connected) - send_command(cs, p_command, at_state); - else - gigaset_add_event(cs, at_state, RSP_NODEV, - NULL, 0, NULL); - } - - spin_lock_irqsave(&cs->lock, flags); - if (!rep->timeout) { - at_state->timer_expires = 0; - at_state->timer_active = 0; - } else if (rep->timeout > 0) { /* new timeout */ - at_state->timer_expires = rep->timeout * 10; - at_state->timer_active = 1; - ++at_state->timer_index; - } - spin_unlock_irqrestore(&cs->lock, flags); - } -} - -static void schedule_sequence(struct cardstate *cs, - struct at_state_t *at_state, int sequence) -{ - cs->cur_at_seq = sequence; - gigaset_add_event(cs, at_state, RSP_INIT, NULL, sequence, NULL); -} - -static void process_command_flags(struct cardstate *cs) -{ - struct at_state_t *at_state = NULL; - struct bc_state *bcs; - int i; - int sequence; - unsigned long flags; - - cs->commands_pending = 0; - - if (cs->cur_at_seq) { - gig_dbg(DEBUG_EVENT, "not searching scheduled commands: busy"); - return; - } - - gig_dbg(DEBUG_EVENT, "searching scheduled commands"); - - sequence = SEQ_NONE; - - /* clear pending_commands and hangup channels on shutdown */ - if (cs->at_state.pending_commands & PC_SHUTDOWN) { - cs->at_state.pending_commands &= ~PC_CIDMODE; - for (i = 0; i < cs->channels; ++i) { - bcs = cs->bcs + i; - at_state = &bcs->at_state; - at_state->pending_commands &= - ~(PC_DLE1 | PC_ACCEPT | PC_DIAL); - if (at_state->cid > 0) - at_state->pending_commands |= PC_HUP; - if (at_state->pending_commands & PC_CID) { - at_state->pending_commands |= PC_NOCID; - at_state->pending_commands &= ~PC_CID; - } - } - } - - /* clear pending_commands and hangup channels on reset */ - if (cs->at_state.pending_commands & PC_INIT) { - cs->at_state.pending_commands &= ~PC_CIDMODE; - for (i = 0; i < cs->channels; ++i) { - bcs = cs->bcs + i; - at_state = &bcs->at_state; - at_state->pending_commands &= - ~(PC_DLE1 | PC_ACCEPT | PC_DIAL); - if (at_state->cid > 0) - at_state->pending_commands |= PC_HUP; - if (cs->mstate == MS_RECOVER) { - if (at_state->pending_commands & PC_CID) { - at_state->pending_commands |= PC_NOCID; - at_state->pending_commands &= ~PC_CID; - } - } - } - } - - /* only switch back to unimodem mode if no commands are pending and - * no channels are up */ - spin_lock_irqsave(&cs->lock, flags); - if (cs->at_state.pending_commands == PC_UMMODE - && !cs->cidmode - && list_empty(&cs->temp_at_states) - && cs->mode == M_CID) { - sequence = SEQ_UMMODE; - at_state = &cs->at_state; - for (i = 0; i < cs->channels; ++i) { - bcs = cs->bcs + i; - if (bcs->at_state.pending_commands || - bcs->at_state.cid > 0) { - sequence = SEQ_NONE; - break; - } - } - } - spin_unlock_irqrestore(&cs->lock, flags); - cs->at_state.pending_commands &= ~PC_UMMODE; - if (sequence != SEQ_NONE) { - schedule_sequence(cs, at_state, sequence); - return; - } - - for (i = 0; i < cs->channels; ++i) { - bcs = cs->bcs + i; - if (bcs->at_state.pending_commands & PC_HUP) { - if (cs->dle) { - cs->curchannel = bcs->channel; - schedule_sequence(cs, &cs->at_state, SEQ_DLE0); - return; - } - bcs->at_state.pending_commands &= ~PC_HUP; - if (bcs->at_state.pending_commands & PC_CID) { - /* not yet dialing: PC_NOCID is sufficient */ - bcs->at_state.pending_commands |= PC_NOCID; - bcs->at_state.pending_commands &= ~PC_CID; - } else { - schedule_sequence(cs, &bcs->at_state, SEQ_HUP); - return; - } - } - if (bcs->at_state.pending_commands & PC_NOCID) { - bcs->at_state.pending_commands &= ~PC_NOCID; - cs->curchannel = bcs->channel; - schedule_sequence(cs, &cs->at_state, SEQ_NOCID); - return; - } else if (bcs->at_state.pending_commands & PC_DLE0) { - bcs->at_state.pending_commands &= ~PC_DLE0; - cs->curchannel = bcs->channel; - schedule_sequence(cs, &cs->at_state, SEQ_DLE0); - return; - } - } - - list_for_each_entry(at_state, &cs->temp_at_states, list) - if (at_state->pending_commands & PC_HUP) { - at_state->pending_commands &= ~PC_HUP; - schedule_sequence(cs, at_state, SEQ_HUP); - return; - } - - if (cs->at_state.pending_commands & PC_INIT) { - cs->at_state.pending_commands &= ~PC_INIT; - cs->dle = 0; - cs->inbuf->inputstate = INS_command; - schedule_sequence(cs, &cs->at_state, SEQ_INIT); - return; - } - if (cs->at_state.pending_commands & PC_SHUTDOWN) { - cs->at_state.pending_commands &= ~PC_SHUTDOWN; - schedule_sequence(cs, &cs->at_state, SEQ_SHUTDOWN); - return; - } - if (cs->at_state.pending_commands & PC_CIDMODE) { - cs->at_state.pending_commands &= ~PC_CIDMODE; - if (cs->mode == M_UNIMODEM) { - cs->retry_count = 1; - schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE); - return; - } - } - - for (i = 0; i < cs->channels; ++i) { - bcs = cs->bcs + i; - if (bcs->at_state.pending_commands & PC_DLE1) { - bcs->at_state.pending_commands &= ~PC_DLE1; - cs->curchannel = bcs->channel; - schedule_sequence(cs, &cs->at_state, SEQ_DLE1); - return; - } - if (bcs->at_state.pending_commands & PC_ACCEPT) { - bcs->at_state.pending_commands &= ~PC_ACCEPT; - schedule_sequence(cs, &bcs->at_state, SEQ_ACCEPT); - return; - } - if (bcs->at_state.pending_commands & PC_DIAL) { - bcs->at_state.pending_commands &= ~PC_DIAL; - schedule_sequence(cs, &bcs->at_state, SEQ_DIAL); - return; - } - if (bcs->at_state.pending_commands & PC_CID) { - switch (cs->mode) { - case M_UNIMODEM: - cs->at_state.pending_commands |= PC_CIDMODE; - gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); - cs->commands_pending = 1; - return; - case M_UNKNOWN: - schedule_init(cs, MS_INIT); - return; - } - bcs->at_state.pending_commands &= ~PC_CID; - cs->curchannel = bcs->channel; - cs->retry_count = 2; - schedule_sequence(cs, &cs->at_state, SEQ_CID); - return; - } - } -} - -static void process_events(struct cardstate *cs) -{ - struct event_t *ev; - unsigned head, tail; - int i; - int check_flags = 0; - int was_busy; - unsigned long flags; - - spin_lock_irqsave(&cs->ev_lock, flags); - head = cs->ev_head; - - for (i = 0; i < 2 * MAX_EVENTS; ++i) { - tail = cs->ev_tail; - if (tail == head) { - if (!check_flags && !cs->commands_pending) - break; - check_flags = 0; - spin_unlock_irqrestore(&cs->ev_lock, flags); - process_command_flags(cs); - spin_lock_irqsave(&cs->ev_lock, flags); - tail = cs->ev_tail; - if (tail == head) { - if (!cs->commands_pending) - break; - continue; - } - } - - ev = cs->events + head; - was_busy = cs->cur_at_seq != SEQ_NONE; - spin_unlock_irqrestore(&cs->ev_lock, flags); - process_event(cs, ev); - spin_lock_irqsave(&cs->ev_lock, flags); - kfree(ev->ptr); - ev->ptr = NULL; - if (was_busy && cs->cur_at_seq == SEQ_NONE) - check_flags = 1; - - head = (head + 1) % MAX_EVENTS; - cs->ev_head = head; - } - - spin_unlock_irqrestore(&cs->ev_lock, flags); - - if (i == 2 * MAX_EVENTS) { - dev_err(cs->dev, - "infinite loop in process_events; aborting.\n"); - } -} - -/* tasklet scheduled on any event received from the Gigaset device - * parameter: - * data ISDN controller state structure - */ -void gigaset_handle_event(unsigned long data) -{ - struct cardstate *cs = (struct cardstate *) data; - - /* handle incoming data on control/common channel */ - if (cs->inbuf->head != cs->inbuf->tail) { - gig_dbg(DEBUG_INTR, "processing new data"); - cs->ops->handle_input(cs->inbuf); - } - - process_events(cs); -} diff --git a/drivers/staging/isdn/gigaset/gigaset.h b/drivers/staging/isdn/gigaset/gigaset.h deleted file mode 100644 index 0ecc2b5ea553..000000000000 --- a/drivers/staging/isdn/gigaset/gigaset.h +++ /dev/null @@ -1,827 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Siemens Gigaset 307x driver - * Common header file for all connection variants - * - * Written by Stefan Eilers - * and Hansjoerg Lipp - * - * ===================================================================== - * ===================================================================== - */ - -#ifndef GIGASET_H -#define GIGASET_H - -/* define global prefix for pr_ macros in linux/kernel.h */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define GIG_VERSION {0, 5, 0, 0} -#define GIG_COMPAT {0, 4, 0, 0} - -#define MAX_REC_PARAMS 10 /* Max. number of params in response string */ -#define MAX_RESP_SIZE 511 /* Max. size of a response string */ - -#define MAX_EVENTS 64 /* size of event queue */ - -#define RBUFSIZE 8192 - -#define GIG_TICK 100 /* in milliseconds */ - -/* timeout values (unit: 1 sec) */ -#define INIT_TIMEOUT 1 - -/* timeout values (unit: 0.1 sec) */ -#define RING_TIMEOUT 3 /* for additional parameters to RING */ -#define BAS_TIMEOUT 20 /* for response to Base USB ops */ -#define ATRDY_TIMEOUT 3 /* for HD_READY_SEND_ATDATA */ - -#define BAS_RETRY 3 /* max. retries for base USB ops */ - -#define MAXACT 3 - -extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */ - -/* debug flags, combine by adding/bitwise OR */ -enum debuglevel { - DEBUG_INTR = 0x00008, /* interrupt processing */ - DEBUG_CMD = 0x00020, /* sent/received LL commands */ - DEBUG_STREAM = 0x00040, /* application data stream I/O events */ - DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */ - DEBUG_LLDATA = 0x00100, /* sent/received LL data */ - DEBUG_EVENT = 0x00200, /* event processing */ - DEBUG_HDLC = 0x00800, /* M10x HDLC processing */ - DEBUG_CHANNEL = 0x01000, /* channel allocation/deallocation */ - DEBUG_TRANSCMD = 0x02000, /* AT-COMMANDS+RESPONSES */ - DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */ - DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data - structures */ - DEBUG_SUSPEND = 0x10000, /* suspend/resume processing */ - DEBUG_OUTPUT = 0x20000, /* output to device */ - DEBUG_ISO = 0x40000, /* isochronous transfers */ - DEBUG_IF = 0x80000, /* character device operations */ - DEBUG_USBREQ = 0x100000, /* USB communication (except payload - data) */ - DEBUG_LOCKCMD = 0x200000, /* AT commands and responses when - MS_LOCKED */ - - DEBUG_ANY = 0x3fffff, /* print message if any of the others is - activated */ -}; - -#ifdef CONFIG_GIGASET_DEBUG - -#define gig_dbg(level, format, arg...) \ - do { \ - if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \ - printk(KERN_DEBUG KBUILD_MODNAME ": " format "\n", \ - ## arg); \ - } while (0) -#define DEBUG_DEFAULT (DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ) - -#else - -#define gig_dbg(level, format, arg...) do {} while (0) -#define DEBUG_DEFAULT 0 - -#endif - -void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, - size_t len, const unsigned char *buf); - -/* connection state */ -#define ZSAU_NONE 0 -#define ZSAU_PROCEEDING 1 -#define ZSAU_CALL_DELIVERED 2 -#define ZSAU_ACTIVE 3 -#define ZSAU_DISCONNECT_IND 4 -#define ZSAU_NULL 5 -#define ZSAU_DISCONNECT_REQ 6 -#define ZSAU_UNKNOWN -1 - -/* USB control transfer requests */ -#define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) -#define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) - -/* interrupt pipe messages */ -#define HD_B1_FLOW_CONTROL 0x80 -#define HD_B2_FLOW_CONTROL 0x81 -#define HD_RECEIVEATDATA_ACK (0x35) /* 3070 */ -#define HD_READY_SEND_ATDATA (0x36) /* 3070 */ -#define HD_OPEN_ATCHANNEL_ACK (0x37) /* 3070 */ -#define HD_CLOSE_ATCHANNEL_ACK (0x38) /* 3070 */ -#define HD_DEVICE_INIT_OK (0x11) /* ISurf USB + 3070 */ -#define HD_OPEN_B1CHANNEL_ACK (0x51) /* ISurf USB + 3070 */ -#define HD_OPEN_B2CHANNEL_ACK (0x52) /* ISurf USB + 3070 */ -#define HD_CLOSE_B1CHANNEL_ACK (0x53) /* ISurf USB + 3070 */ -#define HD_CLOSE_B2CHANNEL_ACK (0x54) /* ISurf USB + 3070 */ -#define HD_SUSPEND_END (0x61) /* ISurf USB */ -#define HD_RESET_INTERRUPT_PIPE_ACK (0xFF) /* ISurf USB + 3070 */ - -/* control requests */ -#define HD_OPEN_B1CHANNEL (0x23) /* ISurf USB + 3070 */ -#define HD_CLOSE_B1CHANNEL (0x24) /* ISurf USB + 3070 */ -#define HD_OPEN_B2CHANNEL (0x25) /* ISurf USB + 3070 */ -#define HD_CLOSE_B2CHANNEL (0x26) /* ISurf USB + 3070 */ -#define HD_RESET_INTERRUPT_PIPE (0x27) /* ISurf USB + 3070 */ -#define HD_DEVICE_INIT_ACK (0x34) /* ISurf USB + 3070 */ -#define HD_WRITE_ATMESSAGE (0x12) /* 3070 */ -#define HD_READ_ATMESSAGE (0x13) /* 3070 */ -#define HD_OPEN_ATCHANNEL (0x28) /* 3070 */ -#define HD_CLOSE_ATCHANNEL (0x29) /* 3070 */ - -/* number of B channels supported by base driver */ -#define BAS_CHANNELS 2 - -/* USB frames for isochronous transfer */ -#define BAS_FRAMETIME 1 /* number of milliseconds between frames */ -#define BAS_NUMFRAMES 8 /* number of frames per URB */ -#define BAS_MAXFRAME 16 /* allocated bytes per frame */ -#define BAS_NORMFRAME 8 /* send size without flow control */ -#define BAS_HIGHFRAME 10 /* " " with positive flow control */ -#define BAS_LOWFRAME 5 /* " " with negative flow control */ -#define BAS_CORRFRAMES 4 /* flow control multiplicator */ - -#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES) /* size of isoc in buf - * per URB */ -#define BAS_OUTBUFSIZE 4096 /* size of common isoc out buffer */ -#define BAS_OUTBUFPAD BAS_MAXFRAME /* size of pad area for isoc out buf */ - -#define BAS_INURBS 3 -#define BAS_OUTURBS 3 - -/* variable commands in struct bc_state */ -#define AT_ISO 0 -#define AT_DIAL 1 -#define AT_MSN 2 -#define AT_BC 3 -#define AT_PROTO 4 -#define AT_TYPE 5 -#define AT_CLIP 6 -/* total number */ -#define AT_NUM 7 - -/* variables in struct at_state_t */ -/* - numeric */ -#define VAR_ZSAU 0 -#define VAR_ZDLE 1 -#define VAR_ZCTP 2 -/* total number */ -#define VAR_NUM 3 -/* - string */ -#define STR_NMBR 0 -#define STR_ZCPN 1 -#define STR_ZCON 2 -#define STR_ZBC 3 -#define STR_ZHLC 4 -/* total number */ -#define STR_NUM 5 - -/* event types */ -#define EV_TIMEOUT -105 -#define EV_IF_VER -106 -#define EV_PROC_CIDMODE -107 -#define EV_SHUTDOWN -108 -#define EV_START -110 -#define EV_STOP -111 -#define EV_IF_LOCK -112 -#define EV_ACCEPT -114 -#define EV_DIAL -115 -#define EV_HUP -116 -#define EV_BC_OPEN -117 -#define EV_BC_CLOSED -118 - -/* input state */ -#define INS_command 0x0001 /* receiving messages (not payload data) */ -#define INS_DLE_char 0x0002 /* DLE flag received (in DLE mode) */ -#define INS_byte_stuff 0x0004 -#define INS_have_data 0x0008 -#define INS_DLE_command 0x0020 /* DLE message start ( X) received */ -#define INS_flag_hunt 0x0040 - -/* channel state */ -#define CHS_D_UP 0x01 -#define CHS_B_UP 0x02 -#define CHS_NOTIFY_LL 0x04 - -#define ICALL_REJECT 0 -#define ICALL_ACCEPT 1 -#define ICALL_IGNORE 2 - -/* device state */ -#define MS_UNINITIALIZED 0 -#define MS_INIT 1 -#define MS_LOCKED 2 -#define MS_SHUTDOWN 3 -#define MS_RECOVER 4 -#define MS_READY 5 - -/* mode */ -#define M_UNKNOWN 0 -#define M_CONFIG 1 -#define M_UNIMODEM 2 -#define M_CID 3 - -/* start mode */ -#define SM_LOCKED 0 -#define SM_ISDN 1 /* default */ - -/* layer 2 protocols (AT^SBPR=...) */ -#define L2_BITSYNC 0 -#define L2_HDLC 1 -#define L2_VOICE 2 - -struct gigaset_ops; -struct gigaset_driver; - -struct usb_cardstate; -struct ser_cardstate; -struct bas_cardstate; - -struct bc_state; -struct usb_bc_state; -struct ser_bc_state; -struct bas_bc_state; - -struct reply_t { - int resp_code; /* RSP_XXXX */ - int min_ConState; /* <0 => ignore */ - int max_ConState; /* <0 => ignore */ - int parameter; /* e.g. ZSAU_XXXX <0: ignore*/ - int new_ConState; /* <0 => ignore */ - int timeout; /* >0 => *HZ; <=0 => TOUT_XXXX*/ - int action[MAXACT]; /* ACT_XXXX */ - char *command; /* NULL==none */ -}; - -extern struct reply_t gigaset_tab_cid[]; -extern struct reply_t gigaset_tab_nocid[]; - -struct inbuf_t { - struct cardstate *cs; - int inputstate; - int head, tail; - unsigned char data[RBUFSIZE]; -}; - -/* isochronous write buffer structure - * circular buffer with pad area for extraction of complete USB frames - * - data[read..nextread-1] is valid data already submitted to the USB subsystem - * - data[nextread..write-1] is valid data yet to be sent - * - data[write] is the next byte to write to - * - in byte-oriented L2 procotols, it is completely free - * - in bit-oriented L2 procotols, it may contain a partial byte of valid data - * - data[write+1..read-1] is free - * - wbits is the number of valid data bits in data[write], starting at the LSB - * - writesem is the semaphore for writing to the buffer: - * if writesem <= 0, data[write..read-1] is currently being written to - * - idle contains the byte value to repeat when the end of valid data is - * reached; if nextread==write (buffer contains no data to send), either the - * BAS_OUTBUFPAD bytes immediately before data[write] (if - * write>=BAS_OUTBUFPAD) or those of the pad area (if write for modem reponses (and - * incoming data for M10x) - * -> on timeout - * -> after setting bits in - * xxx.at_state.pending_command - * (e.g. command from LL) */ - struct tasklet_struct - write_tasklet; /* tasklet for serial output - * (not used in base driver) */ - - /* event queue */ - struct event_t events[MAX_EVENTS]; - unsigned ev_tail, ev_head; - spinlock_t ev_lock; - - /* current modem response */ - unsigned char respdata[MAX_RESP_SIZE + 1]; - unsigned cbytes; - - /* private data of hardware drivers */ - union { - struct usb_cardstate *usb; /* USB hardware driver (m105) */ - struct ser_cardstate *ser; /* serial hardware driver */ - struct bas_cardstate *bas; /* USB hardware driver (base) */ - } hw; -}; - -struct gigaset_driver { - struct list_head list; - spinlock_t lock; /* locks minor tables and blocked */ - struct tty_driver *tty; - unsigned have_tty; - unsigned minor; - unsigned minors; - struct cardstate *cs; - int blocked; - - const struct gigaset_ops *ops; - struct module *owner; -}; - -struct cmdbuf_t { - struct cmdbuf_t *next, *prev; - int len, offset; - struct tasklet_struct *wake_tasklet; - unsigned char buf[0]; -}; - -struct bas_bc_state { - /* isochronous output state */ - int running; - atomic_t corrbytes; - spinlock_t isooutlock; - struct isow_urbctx_t isoouturbs[BAS_OUTURBS]; - struct isow_urbctx_t *isooutdone, *isooutfree, *isooutovfl; - struct isowbuf_t *isooutbuf; - unsigned numsub; /* submitted URB counter - (for diagnostic messages only) */ - struct tasklet_struct sent_tasklet; - - /* isochronous input state */ - spinlock_t isoinlock; - struct urb *isoinurbs[BAS_INURBS]; - unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS]; - struct urb *isoindone; /* completed isoc read URB */ - int isoinstatus; /* status of completed URB */ - int loststatus; /* status of dropped URB */ - unsigned isoinlost; /* number of bytes lost */ - /* state of bit unstuffing algorithm - (in addition to BC_state.inputstate) */ - unsigned seqlen; /* number of '1' bits not yet - unstuffed */ - unsigned inbyte, inbits; /* collected bits for next byte */ - /* statistics */ - unsigned goodbytes; /* bytes correctly received */ - unsigned alignerrs; /* frames with incomplete byte at end */ - unsigned fcserrs; /* FCS errors */ - unsigned frameerrs; /* framing errors */ - unsigned giants; /* long frames */ - unsigned runts; /* short frames */ - unsigned aborts; /* HDLC aborts */ - unsigned shared0s; /* '0' bits shared between flags */ - unsigned stolen0s; /* '0' stuff bits also serving as - leading flag bits */ - struct tasklet_struct rcvd_tasklet; -}; - -struct gigaset_ops { - /* Called from ev-layer.c/interface.c for sending AT commands to the - device */ - int (*write_cmd)(struct cardstate *cs, struct cmdbuf_t *cb); - - /* Called from interface.c for additional device control */ - int (*write_room)(struct cardstate *cs); - int (*chars_in_buffer)(struct cardstate *cs); - int (*brkchars)(struct cardstate *cs, const unsigned char buf[6]); - - /* Called from ev-layer.c after setting up connection - * Should call gigaset_bchannel_up(), when finished. */ - int (*init_bchannel)(struct bc_state *bcs); - - /* Called from ev-layer.c after hanging up - * Should call gigaset_bchannel_down(), when finished. */ - int (*close_bchannel)(struct bc_state *bcs); - - /* Called by gigaset_initcs() for setting up bcs->hw.xxx */ - int (*initbcshw)(struct bc_state *bcs); - - /* Called by gigaset_freecs() for freeing bcs->hw.xxx */ - void (*freebcshw)(struct bc_state *bcs); - - /* Called by gigaset_bchannel_down() for resetting bcs->hw.xxx */ - void (*reinitbcshw)(struct bc_state *bcs); - - /* Called by gigaset_initcs() for setting up cs->hw.xxx */ - int (*initcshw)(struct cardstate *cs); - - /* Called by gigaset_freecs() for freeing cs->hw.xxx */ - void (*freecshw)(struct cardstate *cs); - - /* Called from common.c/interface.c for additional serial port - control */ - int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state, - unsigned new_state); - int (*baud_rate)(struct cardstate *cs, unsigned cflag); - int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag); - - /* Called from LL interface to put an skb into the send-queue. - * After sending is completed, gigaset_skb_sent() must be called - * with the skb's link layer header preserved. */ - int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb); - - /* Called from ev-layer.c to process a block of data - * received through the common/control channel. */ - void (*handle_input)(struct inbuf_t *inbuf); - -}; - -/* = Common structures and definitions ======================================= - */ - -/* Parser states for DLE-Event: - * : "X" "." - * : 0x10 - * : ((a-z)* | (A-Z)* | (0-10)*)+ - */ -#define DLE_FLAG 0x10 - -/* =========================================================================== - * Functions implemented in asyncdata.c - */ - -/* Called from LL interface to put an skb into the send queue. */ -int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb); - -/* Called from ev-layer.c to process a block of data - * received through the common/control channel. */ -void gigaset_m10x_input(struct inbuf_t *inbuf); - -/* =========================================================================== - * Functions implemented in isocdata.c - */ - -/* Called from LL interface to put an skb into the send queue. */ -int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb); - -/* Called from ev-layer.c to process a block of data - * received through the common/control channel. */ -void gigaset_isoc_input(struct inbuf_t *inbuf); - -/* Called from bas-gigaset.c to process a block of data - * received through the isochronous channel */ -void gigaset_isoc_receive(unsigned char *src, unsigned count, - struct bc_state *bcs); - -/* Called from bas-gigaset.c to put a block of data - * into the isochronous output buffer */ -int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len); - -/* Called from bas-gigaset.c to initialize the isochronous output buffer */ -void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle); - -/* Called from bas-gigaset.c to retrieve a block of bytes for sending */ -int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size); - -/* =========================================================================== - * Functions implemented in LL interface - */ - -/* Called from common.c for setting up/shutting down with the ISDN subsystem */ -void gigaset_isdn_regdrv(void); -void gigaset_isdn_unregdrv(void); -int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid); -void gigaset_isdn_unregdev(struct cardstate *cs); - -/* Called from hardware module to indicate completion of an skb */ -void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); -void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb); -void gigaset_isdn_rcv_err(struct bc_state *bcs); - -/* Called from common.c/ev-layer.c to indicate events relevant to the LL */ -void gigaset_isdn_start(struct cardstate *cs); -void gigaset_isdn_stop(struct cardstate *cs); -int gigaset_isdn_icall(struct at_state_t *at_state); -void gigaset_isdn_connD(struct bc_state *bcs); -void gigaset_isdn_hupD(struct bc_state *bcs); -void gigaset_isdn_connB(struct bc_state *bcs); -void gigaset_isdn_hupB(struct bc_state *bcs); - -/* =========================================================================== - * Functions implemented in ev-layer.c - */ - -/* tasklet called from common.c to process queued events */ -void gigaset_handle_event(unsigned long data); - -/* called from isocdata.c / asyncdata.c - * when a complete modem response line has been received */ -void gigaset_handle_modem_response(struct cardstate *cs); - -/* =========================================================================== - * Functions implemented in proc.c - */ - -/* initialize sysfs for device */ -void gigaset_init_dev_sysfs(struct cardstate *cs); -void gigaset_free_dev_sysfs(struct cardstate *cs); - -/* =========================================================================== - * Functions implemented in common.c/gigaset.h - */ - -void gigaset_bcs_reinit(struct bc_state *bcs); -void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, - struct cardstate *cs, int cid); -int gigaset_get_channel(struct bc_state *bcs); -struct bc_state *gigaset_get_free_channel(struct cardstate *cs); -void gigaset_free_channel(struct bc_state *bcs); -int gigaset_get_channels(struct cardstate *cs); -void gigaset_free_channels(struct cardstate *cs); -void gigaset_block_channels(struct cardstate *cs); - -/* Allocate and initialize driver structure. */ -struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, - const char *procname, - const char *devname, - const struct gigaset_ops *ops, - struct module *owner); - -/* Deallocate driver structure. */ -void gigaset_freedriver(struct gigaset_driver *drv); - -struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty); -struct cardstate *gigaset_get_cs_by_id(int id); -void gigaset_blockdriver(struct gigaset_driver *drv); - -/* Allocate and initialize card state. Calls hardware dependent - gigaset_init[b]cs(). */ -struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, - int onechannel, int ignoreframes, - int cidmode, const char *modulename); - -/* Free card state. Calls hardware dependent gigaset_free[b]cs(). */ -void gigaset_freecs(struct cardstate *cs); - -/* Tell common.c that hardware and driver are ready. */ -int gigaset_start(struct cardstate *cs); - -/* Tell common.c that the device is not present any more. */ -void gigaset_stop(struct cardstate *cs); - -/* Tell common.c that the driver is being unloaded. */ -int gigaset_shutdown(struct cardstate *cs); - -/* Append event to the queue. - * Returns NULL on failure or a pointer to the event on success. - * ptr must be kmalloc()ed (and not be freed by the caller). - */ -struct event_t *gigaset_add_event(struct cardstate *cs, - struct at_state_t *at_state, int type, - void *ptr, int parameter, void *arg); - -/* Called on CONFIG1 command from frontend. */ -int gigaset_enterconfigmode(struct cardstate *cs); - -/* cs->lock must not be locked */ -static inline void gigaset_schedule_event(struct cardstate *cs) -{ - unsigned long flags; - spin_lock_irqsave(&cs->lock, flags); - if (cs->running) - tasklet_schedule(&cs->event_tasklet); - spin_unlock_irqrestore(&cs->lock, flags); -} - -/* Tell common.c that B channel has been closed. */ -/* cs->lock must not be locked */ -static inline void gigaset_bchannel_down(struct bc_state *bcs) -{ - gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_CLOSED, NULL, 0, NULL); - gigaset_schedule_event(bcs->cs); -} - -/* Tell common.c that B channel has been opened. */ -/* cs->lock must not be locked */ -static inline void gigaset_bchannel_up(struct bc_state *bcs) -{ - gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_OPEN, NULL, 0, NULL); - gigaset_schedule_event(bcs->cs); -} - -/* set up next receive skb for data mode */ -static inline struct sk_buff *gigaset_new_rx_skb(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - unsigned short hw_hdr_len = cs->hw_hdr_len; - - if (bcs->ignore) { - bcs->rx_skb = NULL; - } else { - bcs->rx_skb = dev_alloc_skb(bcs->rx_bufsize + hw_hdr_len); - if (bcs->rx_skb == NULL) - dev_warn(cs->dev, "could not allocate skb\n"); - else - skb_reserve(bcs->rx_skb, hw_hdr_len); - } - return bcs->rx_skb; -} - -/* append received bytes to inbuf */ -int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, - unsigned numbytes); - -/* =========================================================================== - * Functions implemented in interface.c - */ - -/* initialize interface */ -void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, - const char *devname); -/* release interface */ -void gigaset_if_freedriver(struct gigaset_driver *drv); -/* add minor */ -void gigaset_if_init(struct cardstate *cs); -/* remove minor */ -void gigaset_if_free(struct cardstate *cs); -/* device received data */ -void gigaset_if_receive(struct cardstate *cs, - unsigned char *buffer, size_t len); - -#endif diff --git a/drivers/staging/isdn/gigaset/interface.c b/drivers/staging/isdn/gigaset/interface.c deleted file mode 100644 index 9ddadd07e707..000000000000 --- a/drivers/staging/isdn/gigaset/interface.c +++ /dev/null @@ -1,613 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * interface to user space for the gigaset driver - * - * Copyright (c) 2004 by Hansjoerg Lipp - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include -#include - -/*** our ioctls ***/ - -static int if_lock(struct cardstate *cs, int *arg) -{ - int cmd = *arg; - - gig_dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd); - - if (cmd > 1) - return -EINVAL; - - if (cmd < 0) { - *arg = cs->mstate == MS_LOCKED; - return 0; - } - - if (!cmd && cs->mstate == MS_LOCKED && cs->connected) { - cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR | TIOCM_RTS); - cs->ops->baud_rate(cs, B115200); - cs->ops->set_line_ctrl(cs, CS8); - cs->control_state = TIOCM_DTR | TIOCM_RTS; - } - - cs->waiting = 1; - if (!gigaset_add_event(cs, &cs->at_state, EV_IF_LOCK, - NULL, cmd, NULL)) { - cs->waiting = 0; - return -ENOMEM; - } - gigaset_schedule_event(cs); - - wait_event(cs->waitqueue, !cs->waiting); - - if (cs->cmd_result >= 0) { - *arg = cs->cmd_result; - return 0; - } - - return cs->cmd_result; -} - -static int if_version(struct cardstate *cs, unsigned arg[4]) -{ - static const unsigned version[4] = GIG_VERSION; - static const unsigned compat[4] = GIG_COMPAT; - unsigned cmd = arg[0]; - - gig_dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd); - - switch (cmd) { - case GIGVER_DRIVER: - memcpy(arg, version, sizeof version); - return 0; - case GIGVER_COMPAT: - memcpy(arg, compat, sizeof compat); - return 0; - case GIGVER_FWBASE: - cs->waiting = 1; - if (!gigaset_add_event(cs, &cs->at_state, EV_IF_VER, - NULL, 0, arg)) { - cs->waiting = 0; - return -ENOMEM; - } - gigaset_schedule_event(cs); - - wait_event(cs->waitqueue, !cs->waiting); - - if (cs->cmd_result >= 0) - return 0; - - return cs->cmd_result; - default: - return -EINVAL; - } -} - -static int if_config(struct cardstate *cs, int *arg) -{ - gig_dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg); - - if (*arg != 1) - return -EINVAL; - - if (cs->mstate != MS_LOCKED) - return -EBUSY; - - if (!cs->connected) { - pr_err("%s: not connected\n", __func__); - return -ENODEV; - } - - *arg = 0; - return gigaset_enterconfigmode(cs); -} - -/*** the terminal driver ***/ - -static int if_open(struct tty_struct *tty, struct file *filp) -{ - struct cardstate *cs; - - gig_dbg(DEBUG_IF, "%d+%d: %s()", - tty->driver->minor_start, tty->index, __func__); - - cs = gigaset_get_cs_by_tty(tty); - if (!cs || !try_module_get(cs->driver->owner)) - return -ENODEV; - - if (mutex_lock_interruptible(&cs->mutex)) { - module_put(cs->driver->owner); - return -ERESTARTSYS; - } - tty->driver_data = cs; - - ++cs->port.count; - - if (cs->port.count == 1) { - tty_port_tty_set(&cs->port, tty); - cs->port.low_latency = 1; - } - - mutex_unlock(&cs->mutex); - return 0; -} - -static void if_close(struct tty_struct *tty, struct file *filp) -{ - struct cardstate *cs = tty->driver_data; - - if (!cs) { /* happens if we didn't find cs in open */ - gig_dbg(DEBUG_IF, "%s: no cardstate", __func__); - return; - } - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - mutex_lock(&cs->mutex); - - if (!cs->connected) - gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ - else if (!cs->port.count) - dev_warn(cs->dev, "%s: device not opened\n", __func__); - else if (!--cs->port.count) - tty_port_tty_set(&cs->port, NULL); - - mutex_unlock(&cs->mutex); - - module_put(cs->driver->owner); -} - -static int if_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct cardstate *cs = tty->driver_data; - int retval = -ENODEV; - int int_arg; - unsigned char buf[6]; - unsigned version[4]; - - gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd); - - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; - - if (!cs->connected) { - gig_dbg(DEBUG_IF, "not connected"); - retval = -ENODEV; - } else { - retval = 0; - switch (cmd) { - case GIGASET_REDIR: - retval = get_user(int_arg, (int __user *) arg); - if (retval >= 0) - retval = if_lock(cs, &int_arg); - if (retval >= 0) - retval = put_user(int_arg, (int __user *) arg); - break; - case GIGASET_CONFIG: - retval = get_user(int_arg, (int __user *) arg); - if (retval >= 0) - retval = if_config(cs, &int_arg); - if (retval >= 0) - retval = put_user(int_arg, (int __user *) arg); - break; - case GIGASET_BRKCHARS: - retval = copy_from_user(&buf, - (const unsigned char __user *) arg, 6) - ? -EFAULT : 0; - if (retval >= 0) { - gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS", - 6, buf); - retval = cs->ops->brkchars(cs, buf); - } - break; - case GIGASET_VERSION: - retval = copy_from_user(version, - (unsigned __user *) arg, sizeof version) - ? -EFAULT : 0; - if (retval >= 0) - retval = if_version(cs, version); - if (retval >= 0) - retval = copy_to_user((unsigned __user *) arg, - version, sizeof version) - ? -EFAULT : 0; - break; - default: - gig_dbg(DEBUG_IF, "%s: arg not supported - 0x%04x", - __func__, cmd); - retval = -ENOIOCTLCMD; - } - } - - mutex_unlock(&cs->mutex); - - return retval; -} - -#ifdef CONFIG_COMPAT -static long if_compat_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - return if_ioctl(tty, cmd, (unsigned long)compat_ptr(arg)); -} -#endif - -static int if_tiocmget(struct tty_struct *tty) -{ - struct cardstate *cs = tty->driver_data; - int retval; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; - - retval = cs->control_state & (TIOCM_RTS | TIOCM_DTR); - - mutex_unlock(&cs->mutex); - - return retval; -} - -static int if_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct cardstate *cs = tty->driver_data; - int retval; - unsigned mc; - - gig_dbg(DEBUG_IF, "%u: %s(0x%x, 0x%x)", - cs->minor_index, __func__, set, clear); - - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; - - if (!cs->connected) { - gig_dbg(DEBUG_IF, "not connected"); - retval = -ENODEV; - } else { - mc = (cs->control_state | set) & ~clear & (TIOCM_RTS | TIOCM_DTR); - retval = cs->ops->set_modem_ctrl(cs, cs->control_state, mc); - cs->control_state = mc; - } - - mutex_unlock(&cs->mutex); - - return retval; -} - -static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) -{ - struct cardstate *cs = tty->driver_data; - struct cmdbuf_t *cb; - int retval; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; - - if (!cs->connected) { - gig_dbg(DEBUG_IF, "not connected"); - retval = -ENODEV; - goto done; - } - if (cs->mstate != MS_LOCKED) { - dev_warn(cs->dev, "can't write to unlocked device\n"); - retval = -EBUSY; - goto done; - } - if (count <= 0) { - /* nothing to do */ - retval = 0; - goto done; - } - - cb = kmalloc(sizeof(struct cmdbuf_t) + count, GFP_KERNEL); - if (!cb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - retval = -ENOMEM; - goto done; - } - - memcpy(cb->buf, buf, count); - cb->len = count; - cb->offset = 0; - cb->next = NULL; - cb->wake_tasklet = &cs->if_wake_tasklet; - retval = cs->ops->write_cmd(cs, cb); -done: - mutex_unlock(&cs->mutex); - return retval; -} - -static int if_write_room(struct tty_struct *tty) -{ - struct cardstate *cs = tty->driver_data; - int retval; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; - - if (!cs->connected) { - gig_dbg(DEBUG_IF, "not connected"); - retval = -ENODEV; - } else if (cs->mstate != MS_LOCKED) { - dev_warn(cs->dev, "can't write to unlocked device\n"); - retval = -EBUSY; - } else - retval = cs->ops->write_room(cs); - - mutex_unlock(&cs->mutex); - - return retval; -} - -static int if_chars_in_buffer(struct tty_struct *tty) -{ - struct cardstate *cs = tty->driver_data; - int retval = 0; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - mutex_lock(&cs->mutex); - - if (!cs->connected) - gig_dbg(DEBUG_IF, "not connected"); - else if (cs->mstate != MS_LOCKED) - dev_warn(cs->dev, "can't write to unlocked device\n"); - else - retval = cs->ops->chars_in_buffer(cs); - - mutex_unlock(&cs->mutex); - - return retval; -} - -static void if_throttle(struct tty_struct *tty) -{ - struct cardstate *cs = tty->driver_data; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - mutex_lock(&cs->mutex); - - if (!cs->connected) - gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ - else - gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); - - mutex_unlock(&cs->mutex); -} - -static void if_unthrottle(struct tty_struct *tty) -{ - struct cardstate *cs = tty->driver_data; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - mutex_lock(&cs->mutex); - - if (!cs->connected) - gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ - else - gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); - - mutex_unlock(&cs->mutex); -} - -static void if_set_termios(struct tty_struct *tty, struct ktermios *old) -{ - struct cardstate *cs = tty->driver_data; - unsigned int iflag; - unsigned int cflag; - unsigned int old_cflag; - unsigned int control_state, new_state; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - mutex_lock(&cs->mutex); - - if (!cs->connected) { - gig_dbg(DEBUG_IF, "not connected"); - goto out; - } - - iflag = tty->termios.c_iflag; - cflag = tty->termios.c_cflag; - old_cflag = old ? old->c_cflag : cflag; - gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", - cs->minor_index, iflag, cflag, old_cflag); - - /* get a local copy of the current port settings */ - control_state = cs->control_state; - - /* - * Update baud rate. - * Do not attempt to cache old rates and skip settings, - * disconnects screw such tricks up completely. - * Premature optimization is the root of all evil. - */ - - /* reassert DTR and (maybe) RTS on transition from B0 */ - if ((old_cflag & CBAUD) == B0) { - new_state = control_state | TIOCM_DTR; - /* don't set RTS if using hardware flow control */ - if (!(old_cflag & CRTSCTS)) - new_state |= TIOCM_RTS; - gig_dbg(DEBUG_IF, "%u: from B0 - set DTR%s", - cs->minor_index, - (new_state & TIOCM_RTS) ? " only" : "/RTS"); - cs->ops->set_modem_ctrl(cs, control_state, new_state); - control_state = new_state; - } - - cs->ops->baud_rate(cs, cflag & CBAUD); - - if ((cflag & CBAUD) == B0) { - /* Drop RTS and DTR */ - gig_dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index); - new_state = control_state & ~(TIOCM_DTR | TIOCM_RTS); - cs->ops->set_modem_ctrl(cs, control_state, new_state); - control_state = new_state; - } - - /* - * Update line control register (LCR) - */ - - cs->ops->set_line_ctrl(cs, cflag); - - /* save off the modified port settings */ - cs->control_state = control_state; - -out: - mutex_unlock(&cs->mutex); -} - -static const struct tty_operations if_ops = { - .open = if_open, - .close = if_close, - .ioctl = if_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = if_compat_ioctl, -#endif - .write = if_write, - .write_room = if_write_room, - .chars_in_buffer = if_chars_in_buffer, - .set_termios = if_set_termios, - .throttle = if_throttle, - .unthrottle = if_unthrottle, - .tiocmget = if_tiocmget, - .tiocmset = if_tiocmset, -}; - - -/* wakeup tasklet for the write operation */ -static void if_wake(unsigned long data) -{ - struct cardstate *cs = (struct cardstate *)data; - - tty_port_tty_wakeup(&cs->port); -} - -/*** interface to common ***/ - -void gigaset_if_init(struct cardstate *cs) -{ - struct gigaset_driver *drv; - - drv = cs->driver; - if (!drv->have_tty) - return; - - tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs); - - mutex_lock(&cs->mutex); - cs->tty_dev = tty_port_register_device(&cs->port, drv->tty, - cs->minor_index, NULL); - - if (!IS_ERR(cs->tty_dev)) - dev_set_drvdata(cs->tty_dev, cs); - else { - pr_warn("could not register device to the tty subsystem\n"); - cs->tty_dev = NULL; - } - mutex_unlock(&cs->mutex); -} - -void gigaset_if_free(struct cardstate *cs) -{ - struct gigaset_driver *drv; - - drv = cs->driver; - if (!drv->have_tty) - return; - - tasklet_disable(&cs->if_wake_tasklet); - tasklet_kill(&cs->if_wake_tasklet); - cs->tty_dev = NULL; - tty_unregister_device(drv->tty, cs->minor_index); -} - -/** - * gigaset_if_receive() - pass a received block of data to the tty device - * @cs: device descriptor structure. - * @buffer: received data. - * @len: number of bytes received. - * - * Called by asyncdata/isocdata if a block of data received from the - * device must be sent to userspace through the ttyG* device. - */ -void gigaset_if_receive(struct cardstate *cs, - unsigned char *buffer, size_t len) -{ - tty_insert_flip_string(&cs->port, buffer, len); - tty_flip_buffer_push(&cs->port); -} -EXPORT_SYMBOL_GPL(gigaset_if_receive); - -/* gigaset_if_initdriver - * Initialize tty interface. - * parameters: - * drv Driver - * procname Name of the driver (e.g. for /proc/tty/drivers) - * devname Name of the device files (prefix without minor number) - */ -void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, - const char *devname) -{ - int ret; - struct tty_driver *tty; - - drv->have_tty = 0; - - drv->tty = tty = alloc_tty_driver(drv->minors); - if (tty == NULL) - goto enomem; - - tty->type = TTY_DRIVER_TYPE_SERIAL; - tty->subtype = SERIAL_TYPE_NORMAL; - tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; - - tty->driver_name = procname; - tty->name = devname; - tty->minor_start = drv->minor; - - tty->init_termios = tty_std_termios; - tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - tty_set_operations(tty, &if_ops); - - ret = tty_register_driver(tty); - if (ret < 0) { - pr_err("error %d registering tty driver\n", ret); - goto error; - } - gig_dbg(DEBUG_IF, "tty driver initialized"); - drv->have_tty = 1; - return; - -enomem: - pr_err("out of memory\n"); -error: - if (drv->tty) - put_tty_driver(drv->tty); -} - -void gigaset_if_freedriver(struct gigaset_driver *drv) -{ - if (!drv->have_tty) - return; - - drv->have_tty = 0; - tty_unregister_driver(drv->tty); - put_tty_driver(drv->tty); -} diff --git a/drivers/staging/isdn/gigaset/isocdata.c b/drivers/staging/isdn/gigaset/isocdata.c deleted file mode 100644 index 3ecf6e33ed15..000000000000 --- a/drivers/staging/isdn/gigaset/isocdata.c +++ /dev/null @@ -1,1006 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Common data handling layer for bas_gigaset - * - * Copyright (c) 2005 by Tilman Schmidt , - * Hansjoerg Lipp . - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include - -/* access methods for isowbuf_t */ -/* ============================ */ - -/* initialize buffer structure - */ -void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle) -{ - iwb->read = 0; - iwb->nextread = 0; - iwb->write = 0; - atomic_set(&iwb->writesem, 1); - iwb->wbits = 0; - iwb->idle = idle; - memset(iwb->data + BAS_OUTBUFSIZE, idle, BAS_OUTBUFPAD); -} - -/* compute number of bytes which can be appended to buffer - * so that there is still room to append a maximum frame of flags - */ -static inline int isowbuf_freebytes(struct isowbuf_t *iwb) -{ - int read, write, freebytes; - - read = iwb->read; - write = iwb->write; - freebytes = read - write; - if (freebytes > 0) { - /* no wraparound: need padding space within regular area */ - return freebytes - BAS_OUTBUFPAD; - } else if (read < BAS_OUTBUFPAD) { - /* wraparound: can use space up to end of regular area */ - return BAS_OUTBUFSIZE - write; - } else { - /* following the wraparound yields more space */ - return freebytes + BAS_OUTBUFSIZE - BAS_OUTBUFPAD; - } -} - -/* start writing - * acquire the write semaphore - * return 0 if acquired, <0 if busy - */ -static inline int isowbuf_startwrite(struct isowbuf_t *iwb) -{ - if (!atomic_dec_and_test(&iwb->writesem)) { - atomic_inc(&iwb->writesem); - gig_dbg(DEBUG_ISO, "%s: couldn't acquire iso write semaphore", - __func__); - return -EBUSY; - } - gig_dbg(DEBUG_ISO, - "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d", - __func__, iwb->data[iwb->write], iwb->wbits); - return 0; -} - -/* finish writing - * release the write semaphore - * returns the current write position - */ -static inline int isowbuf_donewrite(struct isowbuf_t *iwb) -{ - int write = iwb->write; - atomic_inc(&iwb->writesem); - return write; -} - -/* append bits to buffer without any checks - * - data contains bits to append, starting at LSB - * - nbits is number of bits to append (0..24) - * must be called with the write semaphore held - * If more than nbits bits are set in data, the extraneous bits are set in the - * buffer too, but the write position is only advanced by nbits. - */ -static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits) -{ - int write = iwb->write; - data <<= iwb->wbits; - data |= iwb->data[write]; - nbits += iwb->wbits; - while (nbits >= 8) { - iwb->data[write++] = data & 0xff; - write %= BAS_OUTBUFSIZE; - data >>= 8; - nbits -= 8; - } - iwb->wbits = nbits; - iwb->data[write] = data & 0xff; - iwb->write = write; -} - -/* put final flag on HDLC bitstream - * also sets the idle fill byte to the correspondingly shifted flag pattern - * must be called with the write semaphore held - */ -static inline void isowbuf_putflag(struct isowbuf_t *iwb) -{ - int write; - - /* add two flags, thus reliably covering one byte */ - isowbuf_putbits(iwb, 0x7e7e, 8); - /* recover the idle flag byte */ - write = iwb->write; - iwb->idle = iwb->data[write]; - gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle); - /* mask extraneous bits in buffer */ - iwb->data[write] &= (1 << iwb->wbits) - 1; -} - -/* retrieve a block of bytes for sending - * The requested number of bytes is provided as a contiguous block. - * If necessary, the frame is filled to the requested number of bytes - * with the idle value. - * returns offset to frame, < 0 on busy or error - */ -int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) -{ - int read, write, limit, src, dst; - unsigned char pbyte; - - read = iwb->nextread; - write = iwb->write; - if (likely(read == write)) { - /* return idle frame */ - return read < BAS_OUTBUFPAD ? - BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD; - } - - limit = read + size; - gig_dbg(DEBUG_STREAM, "%s: read=%d write=%d limit=%d", - __func__, read, write, limit); -#ifdef CONFIG_GIGASET_DEBUG - if (unlikely(size < 0 || size > BAS_OUTBUFPAD)) { - pr_err("invalid size %d\n", size); - return -EINVAL; - } -#endif - - if (read < write) { - /* no wraparound in valid data */ - if (limit >= write) { - /* append idle frame */ - if (isowbuf_startwrite(iwb) < 0) - return -EBUSY; - /* write position could have changed */ - write = iwb->write; - if (limit >= write) { - pbyte = iwb->data[write]; /* save - partial byte */ - limit = write + BAS_OUTBUFPAD; - gig_dbg(DEBUG_STREAM, - "%s: filling %d->%d with %02x", - __func__, write, limit, iwb->idle); - if (write + BAS_OUTBUFPAD < BAS_OUTBUFSIZE) - memset(iwb->data + write, iwb->idle, - BAS_OUTBUFPAD); - else { - /* wraparound, fill entire pad area */ - memset(iwb->data + write, iwb->idle, - BAS_OUTBUFSIZE + BAS_OUTBUFPAD - - write); - limit = 0; - } - gig_dbg(DEBUG_STREAM, - "%s: restoring %02x at %d", - __func__, pbyte, limit); - iwb->data[limit] = pbyte; /* restore - partial byte */ - iwb->write = limit; - } - isowbuf_donewrite(iwb); - } - } else { - /* valid data wraparound */ - if (limit >= BAS_OUTBUFSIZE) { - /* copy wrapped part into pad area */ - src = 0; - dst = BAS_OUTBUFSIZE; - while (dst < limit && src < write) - iwb->data[dst++] = iwb->data[src++]; - if (dst <= limit) { - /* fill pad area with idle byte */ - memset(iwb->data + dst, iwb->idle, - BAS_OUTBUFSIZE + BAS_OUTBUFPAD - dst); - } - limit = src; - } - } - iwb->nextread = limit; - return read; -} - -/* dump_bytes - * write hex bytes to syslog for debugging - */ -static inline void dump_bytes(enum debuglevel level, const char *tag, - unsigned char *bytes, int count) -{ -#ifdef CONFIG_GIGASET_DEBUG - unsigned char c; - static char dbgline[3 * 32 + 1]; - int i = 0; - - if (!(gigaset_debuglevel & level)) - return; - - while (count-- > 0) { - if (i > sizeof(dbgline) - 4) { - dbgline[i] = '\0'; - gig_dbg(level, "%s:%s", tag, dbgline); - i = 0; - } - c = *bytes++; - dbgline[i] = (i && !(i % 12)) ? '-' : ' '; - i++; - dbgline[i++] = hex_asc_hi(c); - dbgline[i++] = hex_asc_lo(c); - } - dbgline[i] = '\0'; - gig_dbg(level, "%s:%s", tag, dbgline); -#endif -} - -/*============================================================================*/ - -/* bytewise HDLC bitstuffing via table lookup - * lookup table: 5 subtables for 0..4 preceding consecutive '1' bits - * index: 256*(number of preceding '1' bits) + (next byte to stuff) - * value: bit 9.. 0 = result bits - * bit 12..10 = number of trailing '1' bits in result - * bit 14..13 = number of bits added by stuffing - */ -static const u16 stufftab[5 * 256] = { -/* previous 1s = 0: */ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x205f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x209f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20df, - 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x048f, - 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x251f, - 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x04af, - 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x255f, - 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x08cf, - 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x299f, - 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef, - 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf, - -/* previous 1s = 1: */ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x206f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x208f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20af, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20cf, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20ef, - 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x250f, - 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x252f, - 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x254f, - 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x256f, - 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x298f, - 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29af, - 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf, - 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef, - -/* previous 1s = 2: */ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x2067, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x2077, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x2087, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x2097, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x20a7, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20b7, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x20c7, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20d7, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x20e7, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20f7, - 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x2507, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x2517, - 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x2527, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x2537, - 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x2547, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x2557, - 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x2567, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x2577, - 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x2987, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x2997, - 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x29a7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29b7, - 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7, - 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7, - -/* previous 1s = 3: */ - 0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b, - 0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b, - 0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b, - 0x0030, 0x0031, 0x0032, 0x2063, 0x0034, 0x0035, 0x0036, 0x206b, 0x0038, 0x0039, 0x003a, 0x2073, 0x003c, 0x003d, 0x203e, 0x207b, - 0x0040, 0x0041, 0x0042, 0x2083, 0x0044, 0x0045, 0x0046, 0x208b, 0x0048, 0x0049, 0x004a, 0x2093, 0x004c, 0x004d, 0x004e, 0x209b, - 0x0050, 0x0051, 0x0052, 0x20a3, 0x0054, 0x0055, 0x0056, 0x20ab, 0x0058, 0x0059, 0x005a, 0x20b3, 0x005c, 0x005d, 0x005e, 0x20bb, - 0x0060, 0x0061, 0x0062, 0x20c3, 0x0064, 0x0065, 0x0066, 0x20cb, 0x0068, 0x0069, 0x006a, 0x20d3, 0x006c, 0x006d, 0x006e, 0x20db, - 0x0070, 0x0071, 0x0072, 0x20e3, 0x0074, 0x0075, 0x0076, 0x20eb, 0x0078, 0x0079, 0x007a, 0x20f3, 0x207c, 0x207d, 0x20be, 0x40fb, - 0x0480, 0x0481, 0x0482, 0x2503, 0x0484, 0x0485, 0x0486, 0x250b, 0x0488, 0x0489, 0x048a, 0x2513, 0x048c, 0x048d, 0x048e, 0x251b, - 0x0490, 0x0491, 0x0492, 0x2523, 0x0494, 0x0495, 0x0496, 0x252b, 0x0498, 0x0499, 0x049a, 0x2533, 0x049c, 0x049d, 0x049e, 0x253b, - 0x04a0, 0x04a1, 0x04a2, 0x2543, 0x04a4, 0x04a5, 0x04a6, 0x254b, 0x04a8, 0x04a9, 0x04aa, 0x2553, 0x04ac, 0x04ad, 0x04ae, 0x255b, - 0x04b0, 0x04b1, 0x04b2, 0x2563, 0x04b4, 0x04b5, 0x04b6, 0x256b, 0x04b8, 0x04b9, 0x04ba, 0x2573, 0x04bc, 0x04bd, 0x253e, 0x257b, - 0x08c0, 0x08c1, 0x08c2, 0x2983, 0x08c4, 0x08c5, 0x08c6, 0x298b, 0x08c8, 0x08c9, 0x08ca, 0x2993, 0x08cc, 0x08cd, 0x08ce, 0x299b, - 0x08d0, 0x08d1, 0x08d2, 0x29a3, 0x08d4, 0x08d5, 0x08d6, 0x29ab, 0x08d8, 0x08d9, 0x08da, 0x29b3, 0x08dc, 0x08dd, 0x08de, 0x29bb, - 0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb, - 0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb, - -/* previous 1s = 4: */ - 0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d, - 0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d, - 0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d, - 0x0030, 0x2061, 0x0032, 0x2065, 0x0034, 0x2069, 0x0036, 0x206d, 0x0038, 0x2071, 0x003a, 0x2075, 0x003c, 0x2079, 0x203e, 0x407d, - 0x0040, 0x2081, 0x0042, 0x2085, 0x0044, 0x2089, 0x0046, 0x208d, 0x0048, 0x2091, 0x004a, 0x2095, 0x004c, 0x2099, 0x004e, 0x209d, - 0x0050, 0x20a1, 0x0052, 0x20a5, 0x0054, 0x20a9, 0x0056, 0x20ad, 0x0058, 0x20b1, 0x005a, 0x20b5, 0x005c, 0x20b9, 0x005e, 0x20bd, - 0x0060, 0x20c1, 0x0062, 0x20c5, 0x0064, 0x20c9, 0x0066, 0x20cd, 0x0068, 0x20d1, 0x006a, 0x20d5, 0x006c, 0x20d9, 0x006e, 0x20dd, - 0x0070, 0x20e1, 0x0072, 0x20e5, 0x0074, 0x20e9, 0x0076, 0x20ed, 0x0078, 0x20f1, 0x007a, 0x20f5, 0x207c, 0x40f9, 0x20be, 0x417d, - 0x0480, 0x2501, 0x0482, 0x2505, 0x0484, 0x2509, 0x0486, 0x250d, 0x0488, 0x2511, 0x048a, 0x2515, 0x048c, 0x2519, 0x048e, 0x251d, - 0x0490, 0x2521, 0x0492, 0x2525, 0x0494, 0x2529, 0x0496, 0x252d, 0x0498, 0x2531, 0x049a, 0x2535, 0x049c, 0x2539, 0x049e, 0x253d, - 0x04a0, 0x2541, 0x04a2, 0x2545, 0x04a4, 0x2549, 0x04a6, 0x254d, 0x04a8, 0x2551, 0x04aa, 0x2555, 0x04ac, 0x2559, 0x04ae, 0x255d, - 0x04b0, 0x2561, 0x04b2, 0x2565, 0x04b4, 0x2569, 0x04b6, 0x256d, 0x04b8, 0x2571, 0x04ba, 0x2575, 0x04bc, 0x2579, 0x253e, 0x467d, - 0x08c0, 0x2981, 0x08c2, 0x2985, 0x08c4, 0x2989, 0x08c6, 0x298d, 0x08c8, 0x2991, 0x08ca, 0x2995, 0x08cc, 0x2999, 0x08ce, 0x299d, - 0x08d0, 0x29a1, 0x08d2, 0x29a5, 0x08d4, 0x29a9, 0x08d6, 0x29ad, 0x08d8, 0x29b1, 0x08da, 0x29b5, 0x08dc, 0x29b9, 0x08de, 0x29bd, - 0x0ce0, 0x2dc1, 0x0ce2, 0x2dc5, 0x0ce4, 0x2dc9, 0x0ce6, 0x2dcd, 0x0ce8, 0x2dd1, 0x0cea, 0x2dd5, 0x0cec, 0x2dd9, 0x0cee, 0x2ddd, - 0x10f0, 0x31e1, 0x10f2, 0x31e5, 0x10f4, 0x31e9, 0x10f6, 0x31ed, 0x20f8, 0x41f1, 0x20fa, 0x41f5, 0x257c, 0x46f9, 0x29be, 0x4b7d -}; - -/* hdlc_bitstuff_byte - * perform HDLC bitstuffing for one input byte (8 bits, LSB first) - * parameters: - * cin input byte - * ones number of trailing '1' bits in result before this step - * iwb pointer to output buffer structure - * (write semaphore must be held) - * return value: - * number of trailing '1' bits in result after this step - */ - -static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin, - int ones) -{ - u16 stuff; - int shiftinc, newones; - - /* get stuffing information for input byte - * value: bit 9.. 0 = result bits - * bit 12..10 = number of trailing '1' bits in result - * bit 14..13 = number of bits added by stuffing - */ - stuff = stufftab[256 * ones + cin]; - shiftinc = (stuff >> 13) & 3; - newones = (stuff >> 10) & 7; - stuff &= 0x3ff; - - /* append stuffed byte to output stream */ - isowbuf_putbits(iwb, stuff, 8 + shiftinc); - return newones; -} - -/* hdlc_buildframe - * Perform HDLC framing with bitstuffing on a byte buffer - * The input buffer is regarded as a sequence of bits, starting with the least - * significant bit of the first byte and ending with the most significant bit - * of the last byte. A 16 bit FCS is appended as defined by RFC 1662. - * Whenever five consecutive '1' bits appear in the resulting bit sequence, a - * '0' bit is inserted after them. - * The resulting bit string and a closing flag pattern (PPP_FLAG, '01111110') - * are appended to the output buffer starting at the given bit position, which - * is assumed to already contain a leading flag. - * The output buffer must have sufficient length; count + count/5 + 6 bytes - * starting at *out are safe and are verified to be present. - * parameters: - * in input buffer - * count number of bytes in input buffer - * iwb pointer to output buffer structure - * (write semaphore must be held) - * return value: - * position of end of packet in output buffer on success, - * -EAGAIN if write semaphore busy or buffer full - */ - -static inline int hdlc_buildframe(struct isowbuf_t *iwb, - unsigned char *in, int count) -{ - int ones; - u16 fcs; - int end; - unsigned char c; - - if (isowbuf_freebytes(iwb) < count + count / 5 + 6 || - isowbuf_startwrite(iwb) < 0) { - gig_dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN", - __func__, isowbuf_freebytes(iwb)); - return -EAGAIN; - } - - dump_bytes(DEBUG_STREAM_DUMP, "snd data", in, count); - - /* bitstuff and checksum input data */ - fcs = PPP_INITFCS; - ones = 0; - while (count-- > 0) { - c = *in++; - ones = hdlc_bitstuff_byte(iwb, c, ones); - fcs = crc_ccitt_byte(fcs, c); - } - - /* bitstuff and append FCS - * (complemented, least significant byte first) */ - fcs ^= 0xffff; - ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones); - ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 0x00ff, ones); - - /* put closing flag and repeat byte for flag idle */ - isowbuf_putflag(iwb); - end = isowbuf_donewrite(iwb); - return end; -} - -/* trans_buildframe - * Append a block of 'transparent' data to the output buffer, - * inverting the bytes. - * The output buffer must have sufficient length; count bytes - * starting at *out are safe and are verified to be present. - * parameters: - * in input buffer - * count number of bytes in input buffer - * iwb pointer to output buffer structure - * (write semaphore must be held) - * return value: - * position of end of packet in output buffer on success, - * -EAGAIN if write semaphore busy or buffer full - */ - -static inline int trans_buildframe(struct isowbuf_t *iwb, - unsigned char *in, int count) -{ - int write; - unsigned char c; - - if (unlikely(count <= 0)) - return iwb->write; - - if (isowbuf_freebytes(iwb) < count || - isowbuf_startwrite(iwb) < 0) { - gig_dbg(DEBUG_ISO, "can't put %d bytes", count); - return -EAGAIN; - } - - gig_dbg(DEBUG_STREAM, "put %d bytes", count); - dump_bytes(DEBUG_STREAM_DUMP, "snd data", in, count); - - write = iwb->write; - do { - c = bitrev8(*in++); - iwb->data[write++] = c; - write %= BAS_OUTBUFSIZE; - } while (--count > 0); - iwb->write = write; - iwb->idle = c; - - return isowbuf_donewrite(iwb); -} - -int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len) -{ - int result; - - switch (bcs->proto2) { - case L2_HDLC: - result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len); - gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", - __func__, len, result); - break; - default: /* assume transparent */ - result = trans_buildframe(bcs->hw.bas->isooutbuf, in, len); - gig_dbg(DEBUG_ISO, "%s: %d bytes trans -> %d", - __func__, len, result); - } - return result; -} - -/* hdlc_putbyte - * append byte c to current skb of B channel structure *bcs, updating fcs - */ -static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs) -{ - bcs->rx_fcs = crc_ccitt_byte(bcs->rx_fcs, c); - if (bcs->rx_skb == NULL) - /* skipping */ - return; - if (bcs->rx_skb->len >= bcs->rx_bufsize) { - dev_warn(bcs->cs->dev, "received oversized packet discarded\n"); - bcs->hw.bas->giants++; - dev_kfree_skb_any(bcs->rx_skb); - bcs->rx_skb = NULL; - return; - } - __skb_put_u8(bcs->rx_skb, c); -} - -/* hdlc_flush - * drop partial HDLC data packet - */ -static inline void hdlc_flush(struct bc_state *bcs) -{ - /* clear skb or allocate new if not skipping */ - if (bcs->rx_skb != NULL) - skb_trim(bcs->rx_skb, 0); - else - gigaset_new_rx_skb(bcs); - - /* reset packet state */ - bcs->rx_fcs = PPP_INITFCS; -} - -/* hdlc_done - * process completed HDLC data packet - */ -static inline void hdlc_done(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - struct sk_buff *procskb; - unsigned int len; - - if (unlikely(bcs->ignore)) { - bcs->ignore--; - hdlc_flush(bcs); - return; - } - procskb = bcs->rx_skb; - if (procskb == NULL) { - /* previous error */ - gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); - gigaset_isdn_rcv_err(bcs); - } else if (procskb->len < 2) { - dev_notice(cs->dev, "received short frame (%d octets)\n", - procskb->len); - bcs->hw.bas->runts++; - dev_kfree_skb_any(procskb); - gigaset_isdn_rcv_err(bcs); - } else if (bcs->rx_fcs != PPP_GOODFCS) { - dev_notice(cs->dev, "frame check error\n"); - bcs->hw.bas->fcserrs++; - dev_kfree_skb_any(procskb); - gigaset_isdn_rcv_err(bcs); - } else { - len = procskb->len; - __skb_trim(procskb, len -= 2); /* subtract FCS */ - gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", __func__, len); - dump_bytes(DEBUG_STREAM_DUMP, - "rcv data", procskb->data, len); - bcs->hw.bas->goodbytes += len; - gigaset_skb_rcvd(bcs, procskb); - } - gigaset_new_rx_skb(bcs); - bcs->rx_fcs = PPP_INITFCS; -} - -/* hdlc_frag - * drop HDLC data packet with non-integral last byte - */ -static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits) -{ - if (unlikely(bcs->ignore)) { - bcs->ignore--; - hdlc_flush(bcs); - return; - } - - dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); - bcs->hw.bas->alignerrs++; - gigaset_isdn_rcv_err(bcs); - __skb_trim(bcs->rx_skb, 0); - bcs->rx_fcs = PPP_INITFCS; -} - -/* bit counts lookup table for HDLC bit unstuffing - * index: input byte - * value: bit 0..3 = number of consecutive '1' bits starting from LSB - * bit 4..6 = number of consecutive '1' bits starting from MSB - * (replacing 8 by 7 to make it fit; the algorithm won't care) - * bit 7 set if there are 5 or more "interior" consecutive '1' bits - */ -static const unsigned char bitcounts[256] = { - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x80, 0x06, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x80, 0x81, 0x80, 0x07, - 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14, - 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x15, - 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14, - 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x90, 0x16, - 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x24, - 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x25, - 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x34, - 0x40, 0x41, 0x40, 0x42, 0x40, 0x41, 0x40, 0x43, 0x50, 0x51, 0x50, 0x52, 0x60, 0x61, 0x70, 0x78 -}; - -/* hdlc_unpack - * perform HDLC frame processing (bit unstuffing, flag detection, FCS - * calculation) on a sequence of received data bytes (8 bits each, LSB first) - * pass on successfully received, complete frames as SKBs via gigaset_skb_rcvd - * notify of errors via gigaset_isdn_rcv_err - * tally frames, errors etc. in BC structure counters - * parameters: - * src received data - * count number of received bytes - * bcs receiving B channel structure - */ -static inline void hdlc_unpack(unsigned char *src, unsigned count, - struct bc_state *bcs) -{ - struct bas_bc_state *ubc = bcs->hw.bas; - int inputstate; - unsigned seqlen, inbyte, inbits; - - /* load previous state: - * inputstate = set of flag bits: - * - INS_flag_hunt: no complete opening flag received since connection - * setup or last abort - * - INS_have_data: at least one complete data byte received since last - * flag - * seqlen = number of consecutive '1' bits in last 7 input stream bits - * (0..7) - * inbyte = accumulated partial data byte (if !INS_flag_hunt) - * inbits = number of valid bits in inbyte, starting at LSB (0..6) - */ - inputstate = bcs->inputstate; - seqlen = ubc->seqlen; - inbyte = ubc->inbyte; - inbits = ubc->inbits; - - /* bit unstuffing a byte a time - * Take your time to understand this; it's straightforward but tedious. - * The "bitcounts" lookup table is used to speed up the counting of - * leading and trailing '1' bits. - */ - while (count--) { - unsigned char c = *src++; - unsigned char tabentry = bitcounts[c]; - unsigned lead1 = tabentry & 0x0f; - unsigned trail1 = (tabentry >> 4) & 0x0f; - - seqlen += lead1; - - if (unlikely(inputstate & INS_flag_hunt)) { - if (c == PPP_FLAG) { - /* flag-in-one */ - inputstate &= ~(INS_flag_hunt | INS_have_data); - inbyte = 0; - inbits = 0; - } else if (seqlen == 6 && trail1 != 7) { - /* flag completed & not followed by abort */ - inputstate &= ~(INS_flag_hunt | INS_have_data); - inbyte = c >> (lead1 + 1); - inbits = 7 - lead1; - if (trail1 >= 8) { - /* interior stuffing: - * omitting the MSB handles most cases, - * correct the incorrectly handled - * cases individually */ - inbits--; - switch (c) { - case 0xbe: - inbyte = 0x3f; - break; - } - } - } - /* else: continue flag-hunting */ - } else if (likely(seqlen < 5 && trail1 < 7)) { - /* streamlined case: 8 data bits, no stuffing */ - inbyte |= c << inbits; - hdlc_putbyte(inbyte & 0xff, bcs); - inputstate |= INS_have_data; - inbyte >>= 8; - /* inbits unchanged */ - } else if (likely(seqlen == 6 && inbits == 7 - lead1 && - trail1 + 1 == inbits && - !(inputstate & INS_have_data))) { - /* streamlined case: flag idle - state unchanged */ - } else if (unlikely(seqlen > 6)) { - /* abort sequence */ - ubc->aborts++; - hdlc_flush(bcs); - inputstate |= INS_flag_hunt; - } else if (seqlen == 6) { - /* closing flag, including (6 - lead1) '1's - * and one '0' from inbits */ - if (inbits > 7 - lead1) { - hdlc_frag(bcs, inbits + lead1 - 7); - inputstate &= ~INS_have_data; - } else { - if (inbits < 7 - lead1) - ubc->stolen0s++; - if (inputstate & INS_have_data) { - hdlc_done(bcs); - inputstate &= ~INS_have_data; - } - } - - if (c == PPP_FLAG) { - /* complete flag, LSB overlaps preceding flag */ - ubc->shared0s++; - inbits = 0; - inbyte = 0; - } else if (trail1 != 7) { - /* remaining bits */ - inbyte = c >> (lead1 + 1); - inbits = 7 - lead1; - if (trail1 >= 8) { - /* interior stuffing: - * omitting the MSB handles most cases, - * correct the incorrectly handled - * cases individually */ - inbits--; - switch (c) { - case 0xbe: - inbyte = 0x3f; - break; - } - } - } else { - /* abort sequence follows, - * skb already empty anyway */ - ubc->aborts++; - inputstate |= INS_flag_hunt; - } - } else { /* (seqlen < 6) && (seqlen == 5 || trail1 >= 7) */ - - if (c == PPP_FLAG) { - /* complete flag */ - if (seqlen == 5) - ubc->stolen0s++; - if (inbits) { - hdlc_frag(bcs, inbits); - inbits = 0; - inbyte = 0; - } else if (inputstate & INS_have_data) - hdlc_done(bcs); - inputstate &= ~INS_have_data; - } else if (trail1 == 7) { - /* abort sequence */ - ubc->aborts++; - hdlc_flush(bcs); - inputstate |= INS_flag_hunt; - } else { - /* stuffed data */ - if (trail1 < 7) { /* => seqlen == 5 */ - /* stuff bit at position lead1, - * no interior stuffing */ - unsigned char mask = (1 << lead1) - 1; - c = (c & mask) | ((c & ~mask) >> 1); - inbyte |= c << inbits; - inbits += 7; - } else if (seqlen < 5) { /* trail1 >= 8 */ - /* interior stuffing: - * omitting the MSB handles most cases, - * correct the incorrectly handled - * cases individually */ - switch (c) { - case 0xbe: - c = 0x7e; - break; - } - inbyte |= c << inbits; - inbits += 7; - } else { /* seqlen == 5 && trail1 >= 8 */ - - /* stuff bit at lead1 *and* interior - * stuffing -- unstuff individually */ - switch (c) { - case 0x7d: - c = 0x3f; - break; - case 0xbe: - c = 0x3f; - break; - case 0x3e: - c = 0x1f; - break; - case 0x7c: - c = 0x3e; - break; - } - inbyte |= c << inbits; - inbits += 6; - } - if (inbits >= 8) { - inbits -= 8; - hdlc_putbyte(inbyte & 0xff, bcs); - inputstate |= INS_have_data; - inbyte >>= 8; - } - } - } - seqlen = trail1 & 7; - } - - /* save new state */ - bcs->inputstate = inputstate; - ubc->seqlen = seqlen; - ubc->inbyte = inbyte; - ubc->inbits = inbits; -} - -/* trans_receive - * pass on received USB frame transparently as SKB via gigaset_skb_rcvd - * invert bytes - * tally frames, errors etc. in BC structure counters - * parameters: - * src received data - * count number of received bytes - * bcs receiving B channel structure - */ -static inline void trans_receive(unsigned char *src, unsigned count, - struct bc_state *bcs) -{ - struct sk_buff *skb; - int dobytes; - unsigned char *dst; - - if (unlikely(bcs->ignore)) { - bcs->ignore--; - return; - } - skb = bcs->rx_skb; - if (skb == NULL) { - skb = gigaset_new_rx_skb(bcs); - if (skb == NULL) - return; - } - dobytes = bcs->rx_bufsize - skb->len; - while (count > 0) { - dst = skb_put(skb, count < dobytes ? count : dobytes); - while (count > 0 && dobytes > 0) { - *dst++ = bitrev8(*src++); - count--; - dobytes--; - } - if (dobytes == 0) { - dump_bytes(DEBUG_STREAM_DUMP, - "rcv data", skb->data, skb->len); - bcs->hw.bas->goodbytes += skb->len; - gigaset_skb_rcvd(bcs, skb); - skb = gigaset_new_rx_skb(bcs); - if (skb == NULL) - return; - dobytes = bcs->rx_bufsize; - } - } -} - -void gigaset_isoc_receive(unsigned char *src, unsigned count, - struct bc_state *bcs) -{ - switch (bcs->proto2) { - case L2_HDLC: - hdlc_unpack(src, count, bcs); - break; - default: /* assume transparent */ - trans_receive(src, count, bcs); - } -} - -/* == data input =========================================================== */ - -/* process a block of received bytes in command mode (mstate != MS_LOCKED) - * Append received bytes to the command response buffer and forward them - * line by line to the response handler. - * Note: Received lines may be terminated by CR, LF, or CR LF, which will be - * removed before passing the line to the response handler. - */ -static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf) -{ - struct cardstate *cs = inbuf->cs; - unsigned cbytes = cs->cbytes; - unsigned char c; - - while (numbytes--) { - c = *src++; - switch (c) { - case '\n': - if (cbytes == 0 && cs->respdata[0] == '\r') { - /* collapse LF with preceding CR */ - cs->respdata[0] = 0; - break; - } - /* fall through */ - case '\r': - /* end of message line, pass to response handler */ - if (cbytes >= MAX_RESP_SIZE) { - dev_warn(cs->dev, "response too large (%d)\n", - cbytes); - cbytes = MAX_RESP_SIZE; - } - cs->cbytes = cbytes; - gigaset_dbg_buffer(DEBUG_TRANSCMD, "received response", - cbytes, cs->respdata); - gigaset_handle_modem_response(cs); - cbytes = 0; - - /* store EOL byte for CRLF collapsing */ - cs->respdata[0] = c; - break; - default: - /* append to line buffer if possible */ - if (cbytes < MAX_RESP_SIZE) - cs->respdata[cbytes] = c; - cbytes++; - } - } - - /* save state */ - cs->cbytes = cbytes; -} - - -/* process a block of data received through the control channel - */ -void gigaset_isoc_input(struct inbuf_t *inbuf) -{ - struct cardstate *cs = inbuf->cs; - unsigned tail, head, numbytes; - unsigned char *src; - - head = inbuf->head; - while (head != (tail = inbuf->tail)) { - gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); - if (head > tail) - tail = RBUFSIZE; - src = inbuf->data + head; - numbytes = tail - head; - gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); - - if (cs->mstate == MS_LOCKED) { - gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", - numbytes, src); - gigaset_if_receive(inbuf->cs, src, numbytes); - } else { - cmd_loop(src, numbytes, inbuf); - } - - head += numbytes; - if (head == RBUFSIZE) - head = 0; - gig_dbg(DEBUG_INTR, "setting head to %u", head); - inbuf->head = head; - } -} - - -/* == data output ========================================================== */ - -/** - * gigaset_isoc_send_skb() - queue an skb for sending - * @bcs: B channel descriptor structure. - * @skb: data to send. - * - * Called by LL to queue an skb for sending, and start transmission if - * necessary. - * Once the payload data has been transmitted completely, gigaset_skb_sent() - * will be called with the skb's link layer header preserved. - * - * Return value: - * number of bytes accepted for sending (skb->len) if ok, - * error code < 0 (eg. -ENODEV) on error - */ -int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb) -{ - int len = skb->len; - unsigned long flags; - - spin_lock_irqsave(&bcs->cs->lock, flags); - if (!bcs->cs->connected) { - spin_unlock_irqrestore(&bcs->cs->lock, flags); - return -ENODEV; - } - - skb_queue_tail(&bcs->squeue, skb); - gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d", - __func__, skb_queue_len(&bcs->squeue)); - - /* tasklet submits URB if necessary */ - tasklet_schedule(&bcs->hw.bas->sent_tasklet); - spin_unlock_irqrestore(&bcs->cs->lock, flags); - - return len; /* ok so far */ -} diff --git a/drivers/staging/isdn/gigaset/proc.c b/drivers/staging/isdn/gigaset/proc.c deleted file mode 100644 index 8914439a4237..000000000000 --- a/drivers/staging/isdn/gigaset/proc.c +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Stuff used by all variants of the driver - * - * Copyright (c) 2001 by Stefan Eilers, - * Hansjoerg Lipp , - * Tilman Schmidt . - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" - -static ssize_t show_cidmode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct cardstate *cs = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", cs->cidmode); -} - -static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cardstate *cs = dev_get_drvdata(dev); - long int value; - char *end; - - value = simple_strtol(buf, &end, 0); - while (*end) - if (!isspace(*end++)) - return -EINVAL; - if (value < 0 || value > 1) - return -EINVAL; - - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; - - cs->waiting = 1; - if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE, - NULL, value, NULL)) { - cs->waiting = 0; - mutex_unlock(&cs->mutex); - return -ENOMEM; - } - gigaset_schedule_event(cs); - - wait_event(cs->waitqueue, !cs->waiting); - - mutex_unlock(&cs->mutex); - - return count; -} - -static DEVICE_ATTR(cidmode, S_IRUGO | S_IWUSR, show_cidmode, set_cidmode); - -/* free sysfs for device */ -void gigaset_free_dev_sysfs(struct cardstate *cs) -{ - if (!cs->tty_dev) - return; - - gig_dbg(DEBUG_INIT, "removing sysfs entries"); - device_remove_file(cs->tty_dev, &dev_attr_cidmode); -} - -/* initialize sysfs for device */ -void gigaset_init_dev_sysfs(struct cardstate *cs) -{ - if (!cs->tty_dev) - return; - - gig_dbg(DEBUG_INIT, "setting up sysfs"); - if (device_create_file(cs->tty_dev, &dev_attr_cidmode)) - pr_err("could not create sysfs attribute\n"); -} diff --git a/drivers/staging/isdn/gigaset/ser-gigaset.c b/drivers/staging/isdn/gigaset/ser-gigaset.c deleted file mode 100644 index 5587e9e7fc73..000000000000 --- a/drivers/staging/isdn/gigaset/ser-gigaset.c +++ /dev/null @@ -1,796 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* This is the serial hardware link layer (HLL) for the Gigaset 307x isdn - * DECT base (aka Sinus 45 isdn) using the RS232 DECT data module M101, - * written as a line discipline. - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include -#include -#include - -/* Version Information */ -#define DRIVER_AUTHOR "Tilman Schmidt" -#define DRIVER_DESC "Serial Driver for Gigaset 307x using Siemens M101" - -#define GIGASET_MINORS 1 -#define GIGASET_MINOR 0 -#define GIGASET_MODULENAME "ser_gigaset" -#define GIGASET_DEVNAME "ttyGS" - -/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */ -#define IF_WRITEBUF 264 - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_LDISC(N_GIGASET_M101); - -static int startmode = SM_ISDN; -module_param(startmode, int, S_IRUGO); -MODULE_PARM_DESC(startmode, "initial operation mode"); -static int cidmode = 1; -module_param(cidmode, int, S_IRUGO); -MODULE_PARM_DESC(cidmode, "stay in CID mode when idle"); - -static struct gigaset_driver *driver; - -struct ser_cardstate { - struct platform_device dev; - struct tty_struct *tty; - atomic_t refcnt; - struct completion dead_cmp; -}; - -static struct platform_driver device_driver = { - .driver = { - .name = GIGASET_MODULENAME, - }, -}; - -static void flush_send_queue(struct cardstate *); - -/* transmit data from current open skb - * result: number of bytes sent or error code < 0 - */ -static int write_modem(struct cardstate *cs) -{ - struct tty_struct *tty = cs->hw.ser->tty; - struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ - struct sk_buff *skb = bcs->tx_skb; - int sent = -EOPNOTSUPP; - - WARN_ON(!tty || !tty->ops || !skb); - - if (!skb->len) { - dev_kfree_skb_any(skb); - bcs->tx_skb = NULL; - return -EINVAL; - } - - set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - if (tty->ops->write) - sent = tty->ops->write(tty, skb->data, skb->len); - gig_dbg(DEBUG_OUTPUT, "write_modem: sent %d", sent); - if (sent < 0) { - /* error */ - flush_send_queue(cs); - return sent; - } - skb_pull(skb, sent); - if (!skb->len) { - /* skb sent completely */ - gigaset_skb_sent(bcs, skb); - - gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", - (unsigned long) skb); - dev_kfree_skb_any(skb); - bcs->tx_skb = NULL; - } - return sent; -} - -/* - * transmit first queued command buffer - * result: number of bytes sent or error code < 0 - */ -static int send_cb(struct cardstate *cs) -{ - struct tty_struct *tty = cs->hw.ser->tty; - struct cmdbuf_t *cb, *tcb; - unsigned long flags; - int sent = 0; - - WARN_ON(!tty || !tty->ops); - - cb = cs->cmdbuf; - if (!cb) - return 0; /* nothing to do */ - - if (cb->len) { - set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - sent = tty->ops->write(tty, cb->buf + cb->offset, cb->len); - if (sent < 0) { - /* error */ - gig_dbg(DEBUG_OUTPUT, "send_cb: write error %d", sent); - flush_send_queue(cs); - return sent; - } - cb->offset += sent; - cb->len -= sent; - gig_dbg(DEBUG_OUTPUT, "send_cb: sent %d, left %u, queued %u", - sent, cb->len, cs->cmdbytes); - } - - while (cb && !cb->len) { - spin_lock_irqsave(&cs->cmdlock, flags); - cs->cmdbytes -= cs->curlen; - tcb = cb; - cs->cmdbuf = cb = cb->next; - if (cb) { - cb->prev = NULL; - cs->curlen = cb->len; - } else { - cs->lastcmdbuf = NULL; - cs->curlen = 0; - } - spin_unlock_irqrestore(&cs->cmdlock, flags); - - if (tcb->wake_tasklet) - tasklet_schedule(tcb->wake_tasklet); - kfree(tcb); - } - return sent; -} - -/* - * send queue tasklet - * If there is already a skb opened, put data to the transfer buffer - * by calling "write_modem". - * Otherwise take a new skb out of the queue. - */ -static void gigaset_modem_fill(unsigned long data) -{ - struct cardstate *cs = (struct cardstate *) data; - struct bc_state *bcs; - struct sk_buff *nextskb; - int sent = 0; - - if (!cs) { - gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); - return; - } - bcs = cs->bcs; - if (!bcs) { - gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); - return; - } - if (!bcs->tx_skb) { - /* no skb is being sent; send command if any */ - sent = send_cb(cs); - gig_dbg(DEBUG_OUTPUT, "%s: send_cb -> %d", __func__, sent); - if (sent) - /* something sent or error */ - return; - - /* no command to send; get skb */ - nextskb = skb_dequeue(&bcs->squeue); - if (!nextskb) - /* no skb either, nothing to do */ - return; - bcs->tx_skb = nextskb; - - gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)", - (unsigned long) bcs->tx_skb); - } - - /* send skb */ - gig_dbg(DEBUG_OUTPUT, "%s: tx_skb", __func__); - if (write_modem(cs) < 0) - gig_dbg(DEBUG_OUTPUT, "%s: write_modem failed", __func__); -} - -/* - * throw away all data queued for sending - */ -static void flush_send_queue(struct cardstate *cs) -{ - struct sk_buff *skb; - struct cmdbuf_t *cb; - unsigned long flags; - - /* command queue */ - spin_lock_irqsave(&cs->cmdlock, flags); - while ((cb = cs->cmdbuf) != NULL) { - cs->cmdbuf = cb->next; - if (cb->wake_tasklet) - tasklet_schedule(cb->wake_tasklet); - kfree(cb); - } - cs->cmdbuf = cs->lastcmdbuf = NULL; - cs->cmdbytes = cs->curlen = 0; - spin_unlock_irqrestore(&cs->cmdlock, flags); - - /* data queue */ - if (cs->bcs->tx_skb) - dev_kfree_skb_any(cs->bcs->tx_skb); - while ((skb = skb_dequeue(&cs->bcs->squeue)) != NULL) - dev_kfree_skb_any(skb); -} - - -/* Gigaset Driver Interface */ -/* ======================== */ - -/* - * queue an AT command string for transmission to the Gigaset device - * parameters: - * cs controller state structure - * buf buffer containing the string to send - * len number of characters to send - * wake_tasklet tasklet to run when transmission is complete, or NULL - * return value: - * number of bytes queued, or error code < 0 - */ -static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb) -{ - unsigned long flags; - - gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? - DEBUG_TRANSCMD : DEBUG_LOCKCMD, - "CMD Transmit", cb->len, cb->buf); - - spin_lock_irqsave(&cs->cmdlock, flags); - cb->prev = cs->lastcmdbuf; - if (cs->lastcmdbuf) - cs->lastcmdbuf->next = cb; - else { - cs->cmdbuf = cb; - cs->curlen = cb->len; - } - cs->cmdbytes += cb->len; - cs->lastcmdbuf = cb; - spin_unlock_irqrestore(&cs->cmdlock, flags); - - spin_lock_irqsave(&cs->lock, flags); - if (cs->connected) - tasklet_schedule(&cs->write_tasklet); - spin_unlock_irqrestore(&cs->lock, flags); - return cb->len; -} - -/* - * tty_driver.write_room interface routine - * return number of characters the driver will accept to be written - * parameter: - * controller state structure - * return value: - * number of characters - */ -static int gigaset_write_room(struct cardstate *cs) -{ - unsigned bytes; - - bytes = cs->cmdbytes; - return bytes < IF_WRITEBUF ? IF_WRITEBUF - bytes : 0; -} - -/* - * tty_driver.chars_in_buffer interface routine - * return number of characters waiting to be sent - * parameter: - * controller state structure - * return value: - * number of characters - */ -static int gigaset_chars_in_buffer(struct cardstate *cs) -{ - return cs->cmdbytes; -} - -/* - * implementation of ioctl(GIGASET_BRKCHARS) - * parameter: - * controller state structure - * return value: - * -EINVAL (unimplemented function) - */ -static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) -{ - /* not implemented */ - return -EINVAL; -} - -/* - * Open B channel - * Called by "do_action" in ev-layer.c - */ -static int gigaset_init_bchannel(struct bc_state *bcs) -{ - /* nothing to do for M10x */ - gigaset_bchannel_up(bcs); - return 0; -} - -/* - * Close B channel - * Called by "do_action" in ev-layer.c - */ -static int gigaset_close_bchannel(struct bc_state *bcs) -{ - /* nothing to do for M10x */ - gigaset_bchannel_down(bcs); - return 0; -} - -/* - * Set up B channel structure - * This is called by "gigaset_initcs" in common.c - */ -static int gigaset_initbcshw(struct bc_state *bcs) -{ - /* unused */ - bcs->hw.ser = NULL; - return 0; -} - -/* - * Free B channel structure - * Called by "gigaset_freebcs" in common.c - */ -static void gigaset_freebcshw(struct bc_state *bcs) -{ - /* unused */ -} - -/* - * Reinitialize B channel structure - * This is called by "bcs_reinit" in common.c - */ -static void gigaset_reinitbcshw(struct bc_state *bcs) -{ - /* nothing to do for M10x */ -} - -/* - * Free hardware specific device data - * This will be called by "gigaset_freecs" in common.c - */ -static void gigaset_freecshw(struct cardstate *cs) -{ - tasklet_kill(&cs->write_tasklet); - if (!cs->hw.ser) - return; - platform_device_unregister(&cs->hw.ser->dev); -} - -static void gigaset_device_release(struct device *dev) -{ - kfree(container_of(dev, struct ser_cardstate, dev.dev)); -} - -/* - * Set up hardware specific device data - * This is called by "gigaset_initcs" in common.c - */ -static int gigaset_initcshw(struct cardstate *cs) -{ - int rc; - struct ser_cardstate *scs; - - scs = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL); - if (!scs) { - pr_err("out of memory\n"); - return -ENOMEM; - } - cs->hw.ser = scs; - - cs->hw.ser->dev.name = GIGASET_MODULENAME; - cs->hw.ser->dev.id = cs->minor_index; - cs->hw.ser->dev.dev.release = gigaset_device_release; - rc = platform_device_register(&cs->hw.ser->dev); - if (rc != 0) { - pr_err("error %d registering platform device\n", rc); - kfree(cs->hw.ser); - cs->hw.ser = NULL; - return rc; - } - - tasklet_init(&cs->write_tasklet, - gigaset_modem_fill, (unsigned long) cs); - return 0; -} - -/* - * set modem control lines - * Parameters: - * card state structure - * modem control line state ([TIOCM_DTR]|[TIOCM_RTS]) - * Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c - * and by "if_lock" and "if_termios" in interface.c - */ -static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) -{ - struct tty_struct *tty = cs->hw.ser->tty; - unsigned int set, clear; - - WARN_ON(!tty || !tty->ops); - /* tiocmset is an optional tty driver method */ - if (!tty->ops->tiocmset) - return -EINVAL; - set = new_state & ~old_state; - clear = old_state & ~new_state; - if (!set && !clear) - return 0; - gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear); - return tty->ops->tiocmset(tty, set, clear); -} - -static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) -{ - return -EINVAL; -} - -static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) -{ - return -EINVAL; -} - -static const struct gigaset_ops ops = { - .write_cmd = gigaset_write_cmd, - .write_room = gigaset_write_room, - .chars_in_buffer = gigaset_chars_in_buffer, - .brkchars = gigaset_brkchars, - .init_bchannel = gigaset_init_bchannel, - .close_bchannel = gigaset_close_bchannel, - .initbcshw = gigaset_initbcshw, - .freebcshw = gigaset_freebcshw, - .reinitbcshw = gigaset_reinitbcshw, - .initcshw = gigaset_initcshw, - .freecshw = gigaset_freecshw, - .set_modem_ctrl = gigaset_set_modem_ctrl, - .baud_rate = gigaset_baud_rate, - .set_line_ctrl = gigaset_set_line_ctrl, - .send_skb = gigaset_m10x_send_skb, /* asyncdata.c */ - .handle_input = gigaset_m10x_input, /* asyncdata.c */ -}; - - -/* Line Discipline Interface */ -/* ========================= */ - -/* helper functions for cardstate refcounting */ -static struct cardstate *cs_get(struct tty_struct *tty) -{ - struct cardstate *cs = tty->disc_data; - - if (!cs || !cs->hw.ser) { - gig_dbg(DEBUG_ANY, "%s: no cardstate", __func__); - return NULL; - } - atomic_inc(&cs->hw.ser->refcnt); - return cs; -} - -static void cs_put(struct cardstate *cs) -{ - if (atomic_dec_and_test(&cs->hw.ser->refcnt)) - complete(&cs->hw.ser->dead_cmp); -} - -/* - * Called by the tty driver when the line discipline is pushed onto the tty. - * Called in process context. - */ -static int -gigaset_tty_open(struct tty_struct *tty) -{ - struct cardstate *cs; - int rc; - - gig_dbg(DEBUG_INIT, "Starting HLL for Gigaset M101"); - - pr_info(DRIVER_DESC "\n"); - - if (!driver) { - pr_err("%s: no driver structure\n", __func__); - return -ENODEV; - } - - /* allocate memory for our device state and initialize it */ - cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); - if (!cs) { - rc = -ENODEV; - goto error; - } - - cs->dev = &cs->hw.ser->dev.dev; - cs->hw.ser->tty = tty; - atomic_set(&cs->hw.ser->refcnt, 1); - init_completion(&cs->hw.ser->dead_cmp); - tty->disc_data = cs; - - /* Set the amount of data we're willing to receive per call - * from the hardware driver to half of the input buffer size - * to leave some reserve. - * Note: We don't do flow control towards the hardware driver. - * If more data is received than will fit into the input buffer, - * it will be dropped and an error will be logged. This should - * never happen as the device is slow and the buffer size ample. - */ - tty->receive_room = RBUFSIZE/2; - - /* OK.. Initialization of the datastructures and the HW is done.. Now - * startup system and notify the LL that we are ready to run - */ - if (startmode == SM_LOCKED) - cs->mstate = MS_LOCKED; - rc = gigaset_start(cs); - if (rc < 0) { - tasklet_kill(&cs->write_tasklet); - goto error; - } - - gig_dbg(DEBUG_INIT, "Startup of HLL done"); - return 0; - -error: - gig_dbg(DEBUG_INIT, "Startup of HLL failed"); - tty->disc_data = NULL; - gigaset_freecs(cs); - return rc; -} - -/* - * Called by the tty driver when the line discipline is removed. - * Called from process context. - */ -static void -gigaset_tty_close(struct tty_struct *tty) -{ - struct cardstate *cs = tty->disc_data; - - gig_dbg(DEBUG_INIT, "Stopping HLL for Gigaset M101"); - - if (!cs) { - gig_dbg(DEBUG_INIT, "%s: no cardstate", __func__); - return; - } - - /* prevent other callers from entering ldisc methods */ - tty->disc_data = NULL; - - if (!cs->hw.ser) - pr_err("%s: no hw cardstate\n", __func__); - else { - /* wait for running methods to finish */ - if (!atomic_dec_and_test(&cs->hw.ser->refcnt)) - wait_for_completion(&cs->hw.ser->dead_cmp); - } - - /* stop operations */ - gigaset_stop(cs); - tasklet_kill(&cs->write_tasklet); - flush_send_queue(cs); - cs->dev = NULL; - gigaset_freecs(cs); - - gig_dbg(DEBUG_INIT, "Shutdown of HLL done"); -} - -/* - * Called by the tty driver when the tty line is hung up. - * Wait for I/O to driver to complete and unregister ISDN device. - * This is already done by the close routine, so just call that. - * Called from process context. - */ -static int gigaset_tty_hangup(struct tty_struct *tty) -{ - gigaset_tty_close(tty); - return 0; -} - -/* - * Ioctl on the tty. - * Called in process context only. - * May be re-entered by multiple ioctl calling threads. - */ -static int -gigaset_tty_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct cardstate *cs = cs_get(tty); - int rc, val; - int __user *p = (int __user *)arg; - - if (!cs) - return -ENXIO; - - switch (cmd) { - - case FIONREAD: - /* unused, always return zero */ - val = 0; - rc = put_user(val, p); - break; - - case TCFLSH: - /* flush our buffers and the serial port's buffer */ - switch (arg) { - case TCIFLUSH: - /* no own input buffer to flush */ - break; - case TCIOFLUSH: - case TCOFLUSH: - flush_send_queue(cs); - break; - } - /* fall through */ - - default: - /* pass through to underlying serial device */ - rc = n_tty_ioctl_helper(tty, file, cmd, arg); - break; - } - cs_put(cs); - return rc; -} - -/* - * Called by the tty driver when a block of data has been received. - * Will not be re-entered while running but other ldisc functions - * may be called in parallel. - * Can be called from hard interrupt level as well as soft interrupt - * level or mainline. - * Parameters: - * tty tty structure - * buf buffer containing received characters - * cflags buffer containing error flags for received characters (ignored) - * count number of received characters - */ -static void -gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, - char *cflags, int count) -{ - struct cardstate *cs = cs_get(tty); - unsigned tail, head, n; - struct inbuf_t *inbuf; - - if (!cs) - return; - inbuf = cs->inbuf; - if (!inbuf) { - dev_err(cs->dev, "%s: no inbuf\n", __func__); - cs_put(cs); - return; - } - - tail = inbuf->tail; - head = inbuf->head; - gig_dbg(DEBUG_INTR, "buffer state: %u -> %u, receive %u bytes", - head, tail, count); - - if (head <= tail) { - /* possible buffer wraparound */ - n = min_t(unsigned, count, RBUFSIZE - tail); - memcpy(inbuf->data + tail, buf, n); - tail = (tail + n) % RBUFSIZE; - buf += n; - count -= n; - } - - if (count > 0) { - /* tail < head and some data left */ - n = head - tail - 1; - if (count > n) { - dev_err(cs->dev, - "inbuf overflow, discarding %d bytes\n", - count - n); - count = n; - } - memcpy(inbuf->data + tail, buf, count); - tail += count; - } - - gig_dbg(DEBUG_INTR, "setting tail to %u", tail); - inbuf->tail = tail; - - /* Everything was received .. Push data into handler */ - gig_dbg(DEBUG_INTR, "%s-->BH", __func__); - gigaset_schedule_event(cs); - cs_put(cs); -} - -/* - * Called by the tty driver when there's room for more data to send. - */ -static void -gigaset_tty_wakeup(struct tty_struct *tty) -{ - struct cardstate *cs = cs_get(tty); - - clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - if (!cs) - return; - tasklet_schedule(&cs->write_tasklet); - cs_put(cs); -} - -static struct tty_ldisc_ops gigaset_ldisc = { - .owner = THIS_MODULE, - .magic = TTY_LDISC_MAGIC, - .name = "ser_gigaset", - .open = gigaset_tty_open, - .close = gigaset_tty_close, - .hangup = gigaset_tty_hangup, - .ioctl = gigaset_tty_ioctl, - .receive_buf = gigaset_tty_receive, - .write_wakeup = gigaset_tty_wakeup, -}; - - -/* Initialization / Shutdown */ -/* ========================= */ - -static int __init ser_gigaset_init(void) -{ - int rc; - - gig_dbg(DEBUG_INIT, "%s", __func__); - rc = platform_driver_register(&device_driver); - if (rc != 0) { - pr_err("error %d registering platform driver\n", rc); - return rc; - } - - /* allocate memory for our driver state and initialize it */ - driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - &ops, THIS_MODULE); - if (!driver) { - rc = -ENOMEM; - goto error; - } - - rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc); - if (rc != 0) { - pr_err("error %d registering line discipline\n", rc); - goto error; - } - - return 0; - -error: - if (driver) { - gigaset_freedriver(driver); - driver = NULL; - } - platform_driver_unregister(&device_driver); - return rc; -} - -static void __exit ser_gigaset_exit(void) -{ - int rc; - - gig_dbg(DEBUG_INIT, "%s", __func__); - - if (driver) { - gigaset_freedriver(driver); - driver = NULL; - } - - rc = tty_unregister_ldisc(N_GIGASET_M101); - if (rc != 0) - pr_err("error %d unregistering line discipline\n", rc); - - platform_driver_unregister(&device_driver); -} - -module_init(ser_gigaset_init); -module_exit(ser_gigaset_exit); diff --git a/drivers/staging/isdn/gigaset/usb-gigaset.c b/drivers/staging/isdn/gigaset/usb-gigaset.c deleted file mode 100644 index 1b9b43659bdf..000000000000 --- a/drivers/staging/isdn/gigaset/usb-gigaset.c +++ /dev/null @@ -1,946 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * USB driver for Gigaset 307x directly or using M105 Data. - * - * Copyright (c) 2001 by Stefan Eilers - * and Hansjoerg Lipp . - * - * This driver was derived from the USB skeleton driver by - * Greg Kroah-Hartman - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include -#include - -/* Version Information */ -#define DRIVER_AUTHOR "Hansjoerg Lipp , Stefan Eilers" -#define DRIVER_DESC "USB Driver for Gigaset 307x using M105" - -/* Module parameters */ - -static int startmode = SM_ISDN; -static int cidmode = 1; - -module_param(startmode, int, S_IRUGO); -module_param(cidmode, int, S_IRUGO); -MODULE_PARM_DESC(startmode, "start in isdn4linux mode"); -MODULE_PARM_DESC(cidmode, "Call-ID mode"); - -#define GIGASET_MINORS 1 -#define GIGASET_MINOR 8 -#define GIGASET_MODULENAME "usb_gigaset" -#define GIGASET_DEVNAME "ttyGU" - -/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */ -#define IF_WRITEBUF 264 - -/* Values for the Gigaset M105 Data */ -#define USB_M105_VENDOR_ID 0x0681 -#define USB_M105_PRODUCT_ID 0x0009 - -/* table of devices that work with this driver */ -static const struct usb_device_id gigaset_table[] = { - { USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, gigaset_table); - -/* - * Control requests (empty fields: 00) - * - * RT|RQ|VALUE|INDEX|LEN |DATA - * In: - * C1 08 01 - * Get flags (1 byte). Bits: 0=dtr,1=rts,3-7:? - * C1 0F ll ll - * Get device information/status (llll: 0x200 and 0x40 seen). - * Real size: I only saw MIN(llll,0x64). - * Contents: seems to be always the same... - * offset 0x00: Length of this structure (0x64) (len: 1,2,3 bytes) - * offset 0x3c: String (16 bit chars): "MCCI USB Serial V2.0" - * rest: ? - * Out: - * 41 11 - * Initialize/reset device ? - * 41 00 xx 00 - * ? (xx=00 or 01; 01 on start, 00 on close) - * 41 07 vv mm - * Set/clear flags vv=value, mm=mask (see RQ 08) - * 41 12 xx - * Used before the following configuration requests are issued - * (with xx=0x0f). I've seen other values<0xf, though. - * 41 01 xx xx - * Set baud rate. xxxx=ceil(0x384000/rate)=trunc(0x383fff/rate)+1. - * 41 03 ps bb - * Set byte size and parity. p: 0x20=even,0x10=odd,0x00=no parity - * [ 0x30: m, 0x40: s ] - * [s: 0: 1 stop bit; 1: 1.5; 2: 2] - * bb: bits/byte (seen 7 and 8) - * 41 13 -- -- -- -- 10 00 ww 00 00 00 xx 00 00 00 yy 00 00 00 zz 00 00 00 - * ?? - * Initialization: 01, 40, 00, 00 - * Open device: 00 40, 00, 00 - * yy and zz seem to be equal, either 0x00 or 0x0a - * (ww,xx) pairs seen: (00,00), (00,40), (01,40), (09,80), (19,80) - * 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13 - * Used after every "configuration sequence" (RQ 12, RQs 01/03/13). - * xx is usually 0x00 but was 0x7e before starting data transfer - * in unimodem mode. So, this might be an array of characters that - * need special treatment ("commit all bufferd data"?), 11=^Q, 13=^S. - * - * Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two - * flags per packet. - */ - -/* functions called if a device of this driver is connected/disconnected */ -static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id); -static void gigaset_disconnect(struct usb_interface *interface); - -/* functions called before/after suspend */ -static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); -static int gigaset_resume(struct usb_interface *intf); -static int gigaset_pre_reset(struct usb_interface *intf); - -static struct gigaset_driver *driver; - -/* usb specific object needed to register this driver with the usb subsystem */ -static struct usb_driver gigaset_usb_driver = { - .name = GIGASET_MODULENAME, - .probe = gigaset_probe, - .disconnect = gigaset_disconnect, - .id_table = gigaset_table, - .suspend = gigaset_suspend, - .resume = gigaset_resume, - .reset_resume = gigaset_resume, - .pre_reset = gigaset_pre_reset, - .post_reset = gigaset_resume, - .disable_hub_initiated_lpm = 1, -}; - -struct usb_cardstate { - struct usb_device *udev; /* usb device pointer */ - struct usb_interface *interface; /* interface for this device */ - int busy; /* bulk output in progress */ - - /* Output buffer */ - unsigned char *bulk_out_buffer; - int bulk_out_size; - int bulk_out_epnum; - struct urb *bulk_out_urb; - - /* Input buffer */ - unsigned char *rcvbuf; - int rcvbuf_size; - struct urb *read_urb; - - char bchars[6]; /* for request 0x19 */ -}; - -static inline unsigned tiocm_to_gigaset(unsigned state) -{ - return ((state & TIOCM_DTR) ? 1 : 0) | ((state & TIOCM_RTS) ? 2 : 0); -} - -static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) -{ - struct usb_device *udev = cs->hw.usb->udev; - unsigned mask, val; - int r; - - mask = tiocm_to_gigaset(old_state ^ new_state); - val = tiocm_to_gigaset(new_state); - - gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); - r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41, - (val & 0xff) | ((mask & 0xff) << 8), 0, - NULL, 0, 2000 /* timeout? */); - if (r < 0) - return r; - return 0; -} - -/* - * Set M105 configuration value - * using undocumented device commands reverse engineered from USB traces - * of the Siemens Windows driver - */ -static int set_value(struct cardstate *cs, u8 req, u16 val) -{ - struct usb_device *udev = cs->hw.usb->udev; - int r, r2; - - gig_dbg(DEBUG_USBREQ, "request %02x (%04x)", - (unsigned)req, (unsigned)val); - r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x12, 0x41, - 0xf /*?*/, 0, NULL, 0, 2000 /*?*/); - /* no idea what this does */ - if (r < 0) { - dev_err(&udev->dev, "error %d on request 0x12\n", -r); - return r; - } - - r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), req, 0x41, - val, 0, NULL, 0, 2000 /*?*/); - if (r < 0) - dev_err(&udev->dev, "error %d on request 0x%02x\n", - -r, (unsigned)req); - - r2 = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, - 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/); - if (r2 < 0) - dev_err(&udev->dev, "error %d on request 0x19\n", -r2); - - return r < 0 ? r : (r2 < 0 ? r2 : 0); -} - -/* - * set the baud rate on the internal serial adapter - * using the undocumented parameter setting command - */ -static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) -{ - u16 val; - u32 rate; - - cflag &= CBAUD; - - switch (cflag) { - case B300: rate = 300; break; - case B600: rate = 600; break; - case B1200: rate = 1200; break; - case B2400: rate = 2400; break; - case B4800: rate = 4800; break; - case B9600: rate = 9600; break; - case B19200: rate = 19200; break; - case B38400: rate = 38400; break; - case B57600: rate = 57600; break; - case B115200: rate = 115200; break; - default: - rate = 9600; - dev_err(cs->dev, "unsupported baudrate request 0x%x," - " using default of B9600\n", cflag); - } - - val = 0x383fff / rate + 1; - - return set_value(cs, 1, val); -} - -/* - * set the line format on the internal serial adapter - * using the undocumented parameter setting command - */ -static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) -{ - u16 val = 0; - - /* set the parity */ - if (cflag & PARENB) - val |= (cflag & PARODD) ? 0x10 : 0x20; - - /* set the number of data bits */ - switch (cflag & CSIZE) { - case CS5: - val |= 5 << 8; break; - case CS6: - val |= 6 << 8; break; - case CS7: - val |= 7 << 8; break; - case CS8: - val |= 8 << 8; break; - default: - dev_err(cs->dev, "CSIZE was not CS5-CS8, using default of 8\n"); - val |= 8 << 8; - break; - } - - /* set the number of stop bits */ - if (cflag & CSTOPB) { - if ((cflag & CSIZE) == CS5) - val |= 1; /* 1.5 stop bits */ - else - val |= 2; /* 2 stop bits */ - } - - return set_value(cs, 3, val); -} - - -/*============================================================================*/ -static int gigaset_init_bchannel(struct bc_state *bcs) -{ - /* nothing to do for M10x */ - gigaset_bchannel_up(bcs); - return 0; -} - -static int gigaset_close_bchannel(struct bc_state *bcs) -{ - /* nothing to do for M10x */ - gigaset_bchannel_down(bcs); - return 0; -} - -static int write_modem(struct cardstate *cs); -static int send_cb(struct cardstate *cs); - - -/* Write tasklet handler: Continue sending current skb, or send command, or - * start sending an skb from the send queue. - */ -static void gigaset_modem_fill(unsigned long data) -{ - struct cardstate *cs = (struct cardstate *) data; - struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ - - gig_dbg(DEBUG_OUTPUT, "modem_fill"); - - if (cs->hw.usb->busy) { - gig_dbg(DEBUG_OUTPUT, "modem_fill: busy"); - return; - } - -again: - if (!bcs->tx_skb) { /* no skb is being sent */ - if (cs->cmdbuf) { /* commands to send? */ - gig_dbg(DEBUG_OUTPUT, "modem_fill: cb"); - if (send_cb(cs) < 0) { - gig_dbg(DEBUG_OUTPUT, - "modem_fill: send_cb failed"); - goto again; /* no callback will be called! */ - } - return; - } - - /* skbs to send? */ - bcs->tx_skb = skb_dequeue(&bcs->squeue); - if (!bcs->tx_skb) - return; - - gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)!", - (unsigned long) bcs->tx_skb); - } - - gig_dbg(DEBUG_OUTPUT, "modem_fill: tx_skb"); - if (write_modem(cs) < 0) { - gig_dbg(DEBUG_OUTPUT, "modem_fill: write_modem failed"); - goto again; /* no callback will be called! */ - } -} - -/* - * Interrupt Input URB completion routine - */ -static void gigaset_read_int_callback(struct urb *urb) -{ - struct cardstate *cs = urb->context; - struct inbuf_t *inbuf = cs->inbuf; - int status = urb->status; - int r; - unsigned numbytes; - unsigned char *src; - unsigned long flags; - - if (!status) { - numbytes = urb->actual_length; - - if (numbytes) { - src = cs->hw.usb->rcvbuf; - if (unlikely(*src)) - dev_warn(cs->dev, - "%s: There was no leading 0, but 0x%02x!\n", - __func__, (unsigned) *src); - ++src; /* skip leading 0x00 */ - --numbytes; - if (gigaset_fill_inbuf(inbuf, src, numbytes)) { - gig_dbg(DEBUG_INTR, "%s-->BH", __func__); - gigaset_schedule_event(inbuf->cs); - } - } else - gig_dbg(DEBUG_INTR, "Received zero block length"); - } else { - /* The urb might have been killed. */ - gig_dbg(DEBUG_ANY, "%s - nonzero status received: %d", - __func__, status); - if (status == -ENOENT || status == -ESHUTDOWN) - /* killed or endpoint shutdown: don't resubmit */ - return; - } - - /* resubmit URB */ - spin_lock_irqsave(&cs->lock, flags); - if (!cs->connected) { - spin_unlock_irqrestore(&cs->lock, flags); - pr_err("%s: disconnected\n", __func__); - return; - } - r = usb_submit_urb(urb, GFP_ATOMIC); - spin_unlock_irqrestore(&cs->lock, flags); - if (r) - dev_err(cs->dev, "error %d resubmitting URB\n", -r); -} - - -/* This callback routine is called when data was transmitted to the device. */ -static void gigaset_write_bulk_callback(struct urb *urb) -{ - struct cardstate *cs = urb->context; - int status = urb->status; - unsigned long flags; - - switch (status) { - case 0: /* normal completion */ - break; - case -ENOENT: /* killed */ - gig_dbg(DEBUG_ANY, "%s: killed", __func__); - cs->hw.usb->busy = 0; - return; - default: - dev_err(cs->dev, "bulk transfer failed (status %d)\n", - -status); - /* That's all we can do. Communication problems - are handled by timeouts or network protocols. */ - } - - spin_lock_irqsave(&cs->lock, flags); - if (!cs->connected) { - pr_err("%s: disconnected\n", __func__); - } else { - cs->hw.usb->busy = 0; - tasklet_schedule(&cs->write_tasklet); - } - spin_unlock_irqrestore(&cs->lock, flags); -} - -static int send_cb(struct cardstate *cs) -{ - struct cmdbuf_t *cb = cs->cmdbuf; - unsigned long flags; - int count; - int status = -ENOENT; - struct usb_cardstate *ucs = cs->hw.usb; - - do { - if (!cb->len) { - spin_lock_irqsave(&cs->cmdlock, flags); - cs->cmdbytes -= cs->curlen; - gig_dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left", - cs->curlen, cs->cmdbytes); - cs->cmdbuf = cb->next; - if (cs->cmdbuf) { - cs->cmdbuf->prev = NULL; - cs->curlen = cs->cmdbuf->len; - } else { - cs->lastcmdbuf = NULL; - cs->curlen = 0; - } - spin_unlock_irqrestore(&cs->cmdlock, flags); - - if (cb->wake_tasklet) - tasklet_schedule(cb->wake_tasklet); - kfree(cb); - - cb = cs->cmdbuf; - } - - if (cb) { - count = min(cb->len, ucs->bulk_out_size); - gig_dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count); - - usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, - usb_sndbulkpipe(ucs->udev, - ucs->bulk_out_epnum), - cb->buf + cb->offset, count, - gigaset_write_bulk_callback, cs); - - cb->offset += count; - cb->len -= count; - ucs->busy = 1; - - spin_lock_irqsave(&cs->lock, flags); - status = cs->connected ? - usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : - -ENODEV; - spin_unlock_irqrestore(&cs->lock, flags); - - if (status) { - ucs->busy = 0; - dev_err(cs->dev, - "could not submit urb (error %d)\n", - -status); - cb->len = 0; /* skip urb => remove cb+wakeup - in next loop cycle */ - } - } - } while (cb && status); /* next command on error */ - - return status; -} - -/* Send command to device. */ -static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb) -{ - unsigned long flags; - int len; - - gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? - DEBUG_TRANSCMD : DEBUG_LOCKCMD, - "CMD Transmit", cb->len, cb->buf); - - spin_lock_irqsave(&cs->cmdlock, flags); - cb->prev = cs->lastcmdbuf; - if (cs->lastcmdbuf) - cs->lastcmdbuf->next = cb; - else { - cs->cmdbuf = cb; - cs->curlen = cb->len; - } - cs->cmdbytes += cb->len; - cs->lastcmdbuf = cb; - spin_unlock_irqrestore(&cs->cmdlock, flags); - - spin_lock_irqsave(&cs->lock, flags); - len = cb->len; - if (cs->connected) - tasklet_schedule(&cs->write_tasklet); - spin_unlock_irqrestore(&cs->lock, flags); - return len; -} - -static int gigaset_write_room(struct cardstate *cs) -{ - unsigned bytes; - - bytes = cs->cmdbytes; - return bytes < IF_WRITEBUF ? IF_WRITEBUF - bytes : 0; -} - -static int gigaset_chars_in_buffer(struct cardstate *cs) -{ - return cs->cmdbytes; -} - -/* - * set the break characters on the internal serial adapter - * using undocumented device commands reverse engineered from USB traces - * of the Siemens Windows driver - */ -static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) -{ - struct usb_device *udev = cs->hw.usb->udev; - - gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf); - memcpy(cs->hw.usb->bchars, buf, 6); - return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, - 0, 0, &buf, 6, 2000); -} - -static void gigaset_freebcshw(struct bc_state *bcs) -{ - /* unused */ -} - -/* Initialize the b-channel structure */ -static int gigaset_initbcshw(struct bc_state *bcs) -{ - /* unused */ - bcs->hw.usb = NULL; - return 0; -} - -static void gigaset_reinitbcshw(struct bc_state *bcs) -{ - /* nothing to do for M10x */ -} - -static void gigaset_freecshw(struct cardstate *cs) -{ - tasklet_kill(&cs->write_tasklet); - kfree(cs->hw.usb); -} - -static int gigaset_initcshw(struct cardstate *cs) -{ - struct usb_cardstate *ucs; - - cs->hw.usb = ucs = - kmalloc(sizeof(struct usb_cardstate), GFP_KERNEL); - if (!ucs) { - pr_err("out of memory\n"); - return -ENOMEM; - } - - ucs->bchars[0] = 0; - ucs->bchars[1] = 0; - ucs->bchars[2] = 0; - ucs->bchars[3] = 0; - ucs->bchars[4] = 0x11; - ucs->bchars[5] = 0x13; - ucs->bulk_out_buffer = NULL; - ucs->bulk_out_urb = NULL; - ucs->read_urb = NULL; - tasklet_init(&cs->write_tasklet, - gigaset_modem_fill, (unsigned long) cs); - - return 0; -} - -/* Send data from current skb to the device. */ -static int write_modem(struct cardstate *cs) -{ - int ret = 0; - int count; - struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ - struct usb_cardstate *ucs = cs->hw.usb; - unsigned long flags; - - gig_dbg(DEBUG_OUTPUT, "len: %d...", bcs->tx_skb->len); - - if (!bcs->tx_skb->len) { - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - return -EINVAL; - } - - /* Copy data to bulk out buffer and transmit data */ - count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); - skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); - skb_pull(bcs->tx_skb, count); - ucs->busy = 1; - gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); - - spin_lock_irqsave(&cs->lock, flags); - if (cs->connected) { - usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, - usb_sndbulkpipe(ucs->udev, - ucs->bulk_out_epnum), - ucs->bulk_out_buffer, count, - gigaset_write_bulk_callback, cs); - ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC); - } else { - ret = -ENODEV; - } - spin_unlock_irqrestore(&cs->lock, flags); - - if (ret) { - dev_err(cs->dev, "could not submit urb (error %d)\n", -ret); - ucs->busy = 0; - } - - if (!bcs->tx_skb->len) { - /* skb sent completely */ - gigaset_skb_sent(bcs, bcs->tx_skb); - - gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", - (unsigned long) bcs->tx_skb); - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - } - - return ret; -} - -static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - int retval; - struct usb_device *udev = interface_to_usbdev(interface); - struct usb_host_interface *hostif = interface->cur_altsetting; - struct cardstate *cs = NULL; - struct usb_cardstate *ucs = NULL; - struct usb_endpoint_descriptor *endpoint; - int buffer_size; - - gig_dbg(DEBUG_ANY, "%s: Check if device matches ...", __func__); - - /* See if the device offered us matches what we can accept */ - if ((le16_to_cpu(udev->descriptor.idVendor) != USB_M105_VENDOR_ID) || - (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID)) { - gig_dbg(DEBUG_ANY, "device ID (0x%x, 0x%x) not for me - skip", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - return -ENODEV; - } - if (hostif->desc.bInterfaceNumber != 0) { - gig_dbg(DEBUG_ANY, "interface %d not for me - skip", - hostif->desc.bInterfaceNumber); - return -ENODEV; - } - if (hostif->desc.bAlternateSetting != 0) { - dev_notice(&udev->dev, "unsupported altsetting %d - skip", - hostif->desc.bAlternateSetting); - return -ENODEV; - } - if (hostif->desc.bInterfaceClass != 255) { - dev_notice(&udev->dev, "unsupported interface class %d - skip", - hostif->desc.bInterfaceClass); - return -ENODEV; - } - - dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); - - /* allocate memory for our device state and initialize it */ - cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); - if (!cs) - return -ENODEV; - ucs = cs->hw.usb; - - /* save off device structure ptrs for later use */ - usb_get_dev(udev); - ucs->udev = udev; - ucs->interface = interface; - cs->dev = &interface->dev; - - /* save address of controller structure */ - usb_set_intfdata(interface, cs); - - endpoint = &hostif->endpoint[0].desc; - - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); - ucs->bulk_out_size = buffer_size; - ucs->bulk_out_epnum = usb_endpoint_num(endpoint); - ucs->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!ucs->bulk_out_buffer) { - dev_err(cs->dev, "Couldn't allocate bulk_out_buffer\n"); - retval = -ENOMEM; - goto error; - } - - ucs->bulk_out_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ucs->bulk_out_urb) { - dev_err(cs->dev, "Couldn't allocate bulk_out_urb\n"); - retval = -ENOMEM; - goto error; - } - - endpoint = &hostif->endpoint[1].desc; - - ucs->busy = 0; - - ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ucs->read_urb) { - dev_err(cs->dev, "No free urbs available\n"); - retval = -ENOMEM; - goto error; - } - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); - ucs->rcvbuf_size = buffer_size; - ucs->rcvbuf = kmalloc(buffer_size, GFP_KERNEL); - if (!ucs->rcvbuf) { - dev_err(cs->dev, "Couldn't allocate rcvbuf\n"); - retval = -ENOMEM; - goto error; - } - /* Fill the interrupt urb and send it to the core */ - usb_fill_int_urb(ucs->read_urb, udev, - usb_rcvintpipe(udev, usb_endpoint_num(endpoint)), - ucs->rcvbuf, buffer_size, - gigaset_read_int_callback, - cs, endpoint->bInterval); - - retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL); - if (retval) { - dev_err(cs->dev, "Could not submit URB (error %d)\n", -retval); - goto error; - } - - /* tell common part that the device is ready */ - if (startmode == SM_LOCKED) - cs->mstate = MS_LOCKED; - - retval = gigaset_start(cs); - if (retval < 0) { - tasklet_kill(&cs->write_tasklet); - goto error; - } - return 0; - -error: - usb_kill_urb(ucs->read_urb); - kfree(ucs->bulk_out_buffer); - usb_free_urb(ucs->bulk_out_urb); - kfree(ucs->rcvbuf); - usb_free_urb(ucs->read_urb); - usb_set_intfdata(interface, NULL); - ucs->read_urb = ucs->bulk_out_urb = NULL; - ucs->rcvbuf = ucs->bulk_out_buffer = NULL; - usb_put_dev(ucs->udev); - ucs->udev = NULL; - ucs->interface = NULL; - gigaset_freecs(cs); - return retval; -} - -static void gigaset_disconnect(struct usb_interface *interface) -{ - struct cardstate *cs; - struct usb_cardstate *ucs; - - cs = usb_get_intfdata(interface); - ucs = cs->hw.usb; - - dev_info(cs->dev, "disconnecting Gigaset USB adapter\n"); - - usb_kill_urb(ucs->read_urb); - - gigaset_stop(cs); - - usb_set_intfdata(interface, NULL); - tasklet_kill(&cs->write_tasklet); - - usb_kill_urb(ucs->bulk_out_urb); - - kfree(ucs->bulk_out_buffer); - usb_free_urb(ucs->bulk_out_urb); - kfree(ucs->rcvbuf); - usb_free_urb(ucs->read_urb); - ucs->read_urb = ucs->bulk_out_urb = NULL; - ucs->rcvbuf = ucs->bulk_out_buffer = NULL; - - usb_put_dev(ucs->udev); - ucs->interface = NULL; - ucs->udev = NULL; - cs->dev = NULL; - gigaset_freecs(cs); -} - -/* gigaset_suspend - * This function is called before the USB connection is suspended or reset. - */ -static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct cardstate *cs = usb_get_intfdata(intf); - - /* stop activity */ - cs->connected = 0; /* prevent rescheduling */ - usb_kill_urb(cs->hw.usb->read_urb); - tasklet_kill(&cs->write_tasklet); - usb_kill_urb(cs->hw.usb->bulk_out_urb); - - gig_dbg(DEBUG_SUSPEND, "suspend complete"); - return 0; -} - -/* gigaset_resume - * This function is called after the USB connection has been resumed or reset. - */ -static int gigaset_resume(struct usb_interface *intf) -{ - struct cardstate *cs = usb_get_intfdata(intf); - int rc; - - /* resubmit interrupt URB */ - cs->connected = 1; - rc = usb_submit_urb(cs->hw.usb->read_urb, GFP_KERNEL); - if (rc) { - dev_err(cs->dev, "Could not submit read URB (error %d)\n", -rc); - return rc; - } - - gig_dbg(DEBUG_SUSPEND, "resume complete"); - return 0; -} - -/* gigaset_pre_reset - * This function is called before the USB connection is reset. - */ -static int gigaset_pre_reset(struct usb_interface *intf) -{ - /* same as suspend */ - return gigaset_suspend(intf, PMSG_ON); -} - -static const struct gigaset_ops ops = { - .write_cmd = gigaset_write_cmd, - .write_room = gigaset_write_room, - .chars_in_buffer = gigaset_chars_in_buffer, - .brkchars = gigaset_brkchars, - .init_bchannel = gigaset_init_bchannel, - .close_bchannel = gigaset_close_bchannel, - .initbcshw = gigaset_initbcshw, - .freebcshw = gigaset_freebcshw, - .reinitbcshw = gigaset_reinitbcshw, - .initcshw = gigaset_initcshw, - .freecshw = gigaset_freecshw, - .set_modem_ctrl = gigaset_set_modem_ctrl, - .baud_rate = gigaset_baud_rate, - .set_line_ctrl = gigaset_set_line_ctrl, - .send_skb = gigaset_m10x_send_skb, - .handle_input = gigaset_m10x_input, -}; - -/* - * This function is called while kernel-module is loaded - */ -static int __init usb_gigaset_init(void) -{ - int result; - - /* allocate memory for our driver state and initialize it */ - driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - &ops, THIS_MODULE); - if (driver == NULL) { - result = -ENOMEM; - goto error; - } - - /* register this driver with the USB subsystem */ - result = usb_register(&gigaset_usb_driver); - if (result < 0) { - pr_err("error %d registering USB driver\n", -result); - goto error; - } - - pr_info(DRIVER_DESC "\n"); - return 0; - -error: - if (driver) - gigaset_freedriver(driver); - driver = NULL; - return result; -} - -/* - * This function is called while unloading the kernel-module - */ -static void __exit usb_gigaset_exit(void) -{ - int i; - - gigaset_blockdriver(driver); /* => probe will fail - * => no gigaset_start any more - */ - - /* stop all connected devices */ - for (i = 0; i < driver->minors; i++) - gigaset_shutdown(driver->cs + i); - - /* from now on, no isdn callback should be possible */ - - /* deregister this driver with the USB subsystem */ - usb_deregister(&gigaset_usb_driver); - /* this will call the disconnect-callback */ - /* from now on, no disconnect/probe callback should be running */ - - gigaset_freedriver(driver); - driver = NULL; -} - - -module_init(usb_gigaset_init); -module_exit(usb_gigaset_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); - -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/isdn/hysdn/Kconfig b/drivers/staging/isdn/hysdn/Kconfig deleted file mode 100644 index 4c8a9283b9dd..000000000000 --- a/drivers/staging/isdn/hysdn/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -config HYSDN - tristate "Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)" - depends on m && PROC_FS && PCI - help - Say Y here if you have one of Hypercope's active PCI ISDN cards - Champ, Ergo and Metro. You will then get a module called hysdn. - Please read the file for more - information. - -config HYSDN_CAPI - bool "HYSDN CAPI 2.0 support" - depends on HYSDN && ISDN_CAPI - help - Say Y here if you like to use Hypercope's CAPI 2.0 interface. diff --git a/drivers/staging/isdn/hysdn/Makefile b/drivers/staging/isdn/hysdn/Makefile deleted file mode 100644 index e01f17f22ebb..000000000000 --- a/drivers/staging/isdn/hysdn/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# Makefile for the hysdn ISDN device driver - -# Each configuration option enables a list of files. - -obj-$(CONFIG_HYSDN) += hysdn.o - -# Multipart objects. - -hysdn-y := hysdn_procconf.o hysdn_proclog.o boardergo.o \ - hysdn_boot.o hysdn_sched.o hysdn_net.o hysdn_init.o -hysdn-$(CONFIG_HYSDN_CAPI) += hycapi.o diff --git a/drivers/staging/isdn/hysdn/boardergo.c b/drivers/staging/isdn/hysdn/boardergo.c deleted file mode 100644 index 2aa2a0e08247..000000000000 --- a/drivers/staging/isdn/hysdn/boardergo.c +++ /dev/null @@ -1,445 +0,0 @@ -/* $Id: boardergo.c,v 1.5.6.7 2001/11/06 21:58:19 kai Exp $ - * - * Linux driver for HYSDN cards, specific routines for ergo type boards. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * As all Linux supported cards Champ2, Ergo and Metro2/4 use the same - * DPRAM interface and layout with only minor differences all related - * stuff is done here, not in separate modules. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" -#include "boardergo.h" - -#define byteout(addr, val) outb(val, addr) -#define bytein(addr) inb(addr) - -/***************************************************/ -/* The cards interrupt handler. Called from system */ -/***************************************************/ -static irqreturn_t -ergo_interrupt(int intno, void *dev_id) -{ - hysdn_card *card = dev_id; /* parameter from irq */ - tErgDpram *dpr; - unsigned long flags; - unsigned char volatile b; - - if (!card) - return IRQ_NONE; /* error -> spurious interrupt */ - if (!card->irq_enabled) - return IRQ_NONE; /* other device interrupting or irq switched off */ - - spin_lock_irqsave(&card->hysdn_lock, flags); /* no further irqs allowed */ - - if (!(bytein(card->iobase + PCI9050_INTR_REG) & PCI9050_INTR_REG_STAT1)) { - spin_unlock_irqrestore(&card->hysdn_lock, flags); /* restore old state */ - return IRQ_NONE; /* no interrupt requested by E1 */ - } - /* clear any pending ints on the board */ - dpr = card->dpram; - b = dpr->ToPcInt; /* clear for ergo */ - b |= dpr->ToPcIntMetro; /* same for metro */ - b |= dpr->ToHyInt; /* and for champ */ - - /* start kernel task immediately after leaving all interrupts */ - if (!card->hw_lock) - schedule_work(&card->irq_queue); - spin_unlock_irqrestore(&card->hysdn_lock, flags); - return IRQ_HANDLED; -} /* ergo_interrupt */ - -/******************************************************************************/ -/* ergo_irq_bh will be called as part of the kernel clearing its shared work */ -/* queue sometime after a call to schedule_work has been made passing our */ -/* work_struct. This task is the only one handling data transfer from or to */ -/* the card after booting. The task may be queued from everywhere */ -/* (interrupts included). */ -/******************************************************************************/ -static void -ergo_irq_bh(struct work_struct *ugli_api) -{ - hysdn_card *card = container_of(ugli_api, hysdn_card, irq_queue); - tErgDpram *dpr; - int again; - unsigned long flags; - - if (card->state != CARD_STATE_RUN) - return; /* invalid call */ - - dpr = card->dpram; /* point to DPRAM */ - - spin_lock_irqsave(&card->hysdn_lock, flags); - if (card->hw_lock) { - spin_unlock_irqrestore(&card->hysdn_lock, flags); /* hardware currently unavailable */ - return; - } - card->hw_lock = 1; /* we now lock the hardware */ - - do { - again = 0; /* assume loop not to be repeated */ - - if (!dpr->ToHyFlag) { - /* we are able to send a buffer */ - - if (hysdn_sched_tx(card, dpr->ToHyBuf, &dpr->ToHySize, &dpr->ToHyChannel, - ERG_TO_HY_BUF_SIZE)) { - dpr->ToHyFlag = 1; /* enable tx */ - again = 1; /* restart loop */ - } - } /* we are able to send a buffer */ - if (dpr->ToPcFlag) { - /* a message has arrived for us, handle it */ - - if (hysdn_sched_rx(card, dpr->ToPcBuf, dpr->ToPcSize, dpr->ToPcChannel)) { - dpr->ToPcFlag = 0; /* we worked the data */ - again = 1; /* restart loop */ - } - } /* a message has arrived for us */ - if (again) { - dpr->ToHyInt = 1; - dpr->ToPcInt = 1; /* interrupt to E1 for all cards */ - } else - card->hw_lock = 0; /* free hardware again */ - } while (again); /* until nothing more to do */ - - spin_unlock_irqrestore(&card->hysdn_lock, flags); -} /* ergo_irq_bh */ - - -/*********************************************************/ -/* stop the card (hardware reset) and disable interrupts */ -/*********************************************************/ -static void -ergo_stopcard(hysdn_card *card) -{ - unsigned long flags; - unsigned char val; - - hysdn_net_release(card); /* first release the net device if existing */ -#ifdef CONFIG_HYSDN_CAPI - hycapi_capi_stop(card); -#endif /* CONFIG_HYSDN_CAPI */ - spin_lock_irqsave(&card->hysdn_lock, flags); - val = bytein(card->iobase + PCI9050_INTR_REG); /* get actual value */ - val &= ~(PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1); /* mask irq */ - byteout(card->iobase + PCI9050_INTR_REG, val); - card->irq_enabled = 0; - byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RESET); /* reset E1 processor */ - card->state = CARD_STATE_UNUSED; - card->err_log_state = ERRLOG_STATE_OFF; /* currently no log active */ - - spin_unlock_irqrestore(&card->hysdn_lock, flags); -} /* ergo_stopcard */ - -/**************************************************************************/ -/* enable or disable the cards error log. The event is queued if possible */ -/**************************************************************************/ -static void -ergo_set_errlog_state(hysdn_card *card, int on) -{ - unsigned long flags; - - if (card->state != CARD_STATE_RUN) { - card->err_log_state = ERRLOG_STATE_OFF; /* must be off */ - return; - } - spin_lock_irqsave(&card->hysdn_lock, flags); - - if (((card->err_log_state == ERRLOG_STATE_OFF) && !on) || - ((card->err_log_state == ERRLOG_STATE_ON) && on)) { - spin_unlock_irqrestore(&card->hysdn_lock, flags); - return; /* nothing to do */ - } - if (on) - card->err_log_state = ERRLOG_STATE_START; /* request start */ - else - card->err_log_state = ERRLOG_STATE_STOP; /* request stop */ - - spin_unlock_irqrestore(&card->hysdn_lock, flags); - schedule_work(&card->irq_queue); -} /* ergo_set_errlog_state */ - -/******************************************/ -/* test the cards RAM and return 0 if ok. */ -/******************************************/ -static const char TestText[36] = "This Message is filler, why read it"; - -static int -ergo_testram(hysdn_card *card) -{ - tErgDpram *dpr = card->dpram; - - memset(dpr->TrapTable, 0, sizeof(dpr->TrapTable)); /* clear all Traps */ - dpr->ToHyInt = 1; /* E1 INTR state forced */ - - memcpy(&dpr->ToHyBuf[ERG_TO_HY_BUF_SIZE - sizeof(TestText)], TestText, - sizeof(TestText)); - if (memcmp(&dpr->ToHyBuf[ERG_TO_HY_BUF_SIZE - sizeof(TestText)], TestText, - sizeof(TestText))) - return (-1); - - memcpy(&dpr->ToPcBuf[ERG_TO_PC_BUF_SIZE - sizeof(TestText)], TestText, - sizeof(TestText)); - if (memcmp(&dpr->ToPcBuf[ERG_TO_PC_BUF_SIZE - sizeof(TestText)], TestText, - sizeof(TestText))) - return (-1); - - return (0); -} /* ergo_testram */ - -/*****************************************************************************/ -/* this function is intended to write stage 1 boot image to the cards buffer */ -/* this is done in two steps. First the 1024 hi-words are written (offs=0), */ -/* then the 1024 lo-bytes are written. The remaining DPRAM is cleared, the */ -/* PCI-write-buffers flushed and the card is taken out of reset. */ -/* The function then waits for a reaction of the E1 processor or a timeout. */ -/* Negative return values are interpreted as errors. */ -/*****************************************************************************/ -static int -ergo_writebootimg(struct HYSDN_CARD *card, unsigned char *buf, - unsigned long offs) -{ - unsigned char *dst; - tErgDpram *dpram; - int cnt = (BOOT_IMG_SIZE >> 2); /* number of words to move and swap (byte order!) */ - - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: write bootldr offs=0x%lx ", offs); - - dst = card->dpram; /* pointer to start of DPRAM */ - dst += (offs + ERG_DPRAM_FILL_SIZE); /* offset in the DPRAM */ - while (cnt--) { - *dst++ = *(buf + 1); /* high byte */ - *dst++ = *buf; /* low byte */ - dst += 2; /* point to next longword */ - buf += 2; /* buffer only filled with words */ - } - - /* if low words (offs = 2) have been written, clear the rest of the DPRAM, */ - /* flush the PCI-write-buffer and take the E1 out of reset */ - if (offs) { - memset(card->dpram, 0, ERG_DPRAM_FILL_SIZE); /* fill the DPRAM still not cleared */ - dpram = card->dpram; /* get pointer to dpram structure */ - dpram->ToHyNoDpramErrLog = 0xFF; /* write a dpram register */ - while (!dpram->ToHyNoDpramErrLog); /* reread volatile register to flush PCI */ - - byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RUN); /* start E1 processor */ - /* the interrupts are still masked */ - - msleep_interruptible(20); /* Timeout 20ms */ - - if (((tDpramBootSpooler *) card->dpram)->Len != DPRAM_SPOOLER_DATA_SIZE) { - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: write bootldr no answer"); - return (-ERR_BOOTIMG_FAIL); - } - } /* start_boot_img */ - return (0); /* successful */ -} /* ergo_writebootimg */ - -/********************************************************************************/ -/* ergo_writebootseq writes the buffer containing len bytes to the E1 processor */ -/* using the boot spool mechanism. If everything works fine 0 is returned. In */ -/* case of errors a negative error value is returned. */ -/********************************************************************************/ -static int -ergo_writebootseq(struct HYSDN_CARD *card, unsigned char *buf, int len) -{ - tDpramBootSpooler *sp = (tDpramBootSpooler *) card->dpram; - unsigned char *dst; - unsigned char buflen; - int nr_write; - unsigned char tmp_rdptr; - unsigned char wr_mirror; - int i; - - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: write boot seq len=%d ", len); - - dst = sp->Data; /* point to data in spool structure */ - buflen = sp->Len; /* maximum len of spooled data */ - wr_mirror = sp->WrPtr; /* only once read */ - - /* try until all bytes written or error */ - i = 0x1000; /* timeout value */ - while (len) { - - /* first determine the number of bytes that may be buffered */ - do { - tmp_rdptr = sp->RdPtr; /* first read the pointer */ - i--; /* decrement timeout */ - } while (i && (tmp_rdptr != sp->RdPtr)); /* wait for stable pointer */ - - if (!i) { - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: write boot seq timeout"); - return (-ERR_BOOTSEQ_FAIL); /* value not stable -> timeout */ - } - if ((nr_write = tmp_rdptr - wr_mirror - 1) < 0) - nr_write += buflen; /* now we got number of free bytes - 1 in buffer */ - - if (!nr_write) - continue; /* no free bytes in buffer */ - - if (nr_write > len) - nr_write = len; /* limit if last few bytes */ - i = 0x1000; /* reset timeout value */ - - /* now we know how much bytes we may put in the puffer */ - len -= nr_write; /* we savely could adjust len before output */ - while (nr_write--) { - *(dst + wr_mirror) = *buf++; /* output one byte */ - if (++wr_mirror >= buflen) - wr_mirror = 0; - sp->WrPtr = wr_mirror; /* announce the next byte to E1 */ - } /* while (nr_write) */ - - } /* while (len) */ - return (0); -} /* ergo_writebootseq */ - -/***********************************************************************************/ -/* ergo_waitpofready waits for a maximum of 10 seconds for the completition of the */ -/* boot process. If the process has been successful 0 is returned otherwise a */ -/* negative error code is returned. */ -/***********************************************************************************/ -static int -ergo_waitpofready(struct HYSDN_CARD *card) -{ - tErgDpram *dpr = card->dpram; /* pointer to DPRAM structure */ - int timecnt = 10000 / 50; /* timeout is 10 secs max. */ - unsigned long flags; - int msg_size; - int i; - - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: waiting for pof ready"); - while (timecnt--) { - /* wait until timeout */ - - if (dpr->ToPcFlag) { - /* data has arrived */ - - if ((dpr->ToPcChannel != CHAN_SYSTEM) || - (dpr->ToPcSize < MIN_RDY_MSG_SIZE) || - (dpr->ToPcSize > MAX_RDY_MSG_SIZE) || - ((*(unsigned long *) dpr->ToPcBuf) != RDY_MAGIC)) - break; /* an error occurred */ - - /* Check for additional data delivered during SysReady */ - msg_size = dpr->ToPcSize - RDY_MAGIC_SIZE; - if (msg_size > 0) - if (EvalSysrTokData(card, dpr->ToPcBuf + RDY_MAGIC_SIZE, msg_size)) - break; - - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "ERGO: pof boot success"); - spin_lock_irqsave(&card->hysdn_lock, flags); - - card->state = CARD_STATE_RUN; /* now card is running */ - /* enable the cards interrupt */ - byteout(card->iobase + PCI9050_INTR_REG, - bytein(card->iobase + PCI9050_INTR_REG) | - (PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1)); - card->irq_enabled = 1; /* we are ready to receive interrupts */ - - dpr->ToPcFlag = 0; /* reset data indicator */ - dpr->ToHyInt = 1; - dpr->ToPcInt = 1; /* interrupt to E1 for all cards */ - - spin_unlock_irqrestore(&card->hysdn_lock, flags); - if ((hynet_enable & (1 << card->myid)) - && (i = hysdn_net_create(card))) - { - ergo_stopcard(card); - card->state = CARD_STATE_BOOTERR; - return (i); - } -#ifdef CONFIG_HYSDN_CAPI - if ((i = hycapi_capi_create(card))) { - printk(KERN_WARNING "HYSDN: failed to create capi-interface.\n"); - } -#endif /* CONFIG_HYSDN_CAPI */ - return (0); /* success */ - } /* data has arrived */ - msleep_interruptible(50); /* Timeout 50ms */ - } /* wait until timeout */ - - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: pof boot ready timeout"); - return (-ERR_POF_TIMEOUT); -} /* ergo_waitpofready */ - - - -/************************************************************************************/ -/* release the cards hardware. Before releasing do a interrupt disable and hardware */ -/* reset. Also unmap dpram. */ -/* Use only during module release. */ -/************************************************************************************/ -static void -ergo_releasehardware(hysdn_card *card) -{ - ergo_stopcard(card); /* first stop the card if not already done */ - free_irq(card->irq, card); /* release interrupt */ - release_region(card->iobase + PCI9050_INTR_REG, 1); /* release all io ports */ - release_region(card->iobase + PCI9050_USER_IO, 1); - iounmap(card->dpram); - card->dpram = NULL; /* release shared mem */ -} /* ergo_releasehardware */ - - -/*********************************************************************************/ -/* acquire the needed hardware ports and map dpram. If an error occurs a nonzero */ -/* value is returned. */ -/* Use only during module init. */ -/*********************************************************************************/ -int -ergo_inithardware(hysdn_card *card) -{ - if (!request_region(card->iobase + PCI9050_INTR_REG, 1, "HYSDN")) - return (-1); - if (!request_region(card->iobase + PCI9050_USER_IO, 1, "HYSDN")) { - release_region(card->iobase + PCI9050_INTR_REG, 1); - return (-1); /* ports already in use */ - } - card->memend = card->membase + ERG_DPRAM_PAGE_SIZE - 1; - if (!(card->dpram = ioremap(card->membase, ERG_DPRAM_PAGE_SIZE))) { - release_region(card->iobase + PCI9050_INTR_REG, 1); - release_region(card->iobase + PCI9050_USER_IO, 1); - return (-1); - } - - ergo_stopcard(card); /* disable interrupts */ - if (request_irq(card->irq, ergo_interrupt, IRQF_SHARED, "HYSDN", card)) { - ergo_releasehardware(card); /* return the acquired hardware */ - return (-1); - } - /* success, now setup the function pointers */ - card->stopcard = ergo_stopcard; - card->releasehardware = ergo_releasehardware; - card->testram = ergo_testram; - card->writebootimg = ergo_writebootimg; - card->writebootseq = ergo_writebootseq; - card->waitpofready = ergo_waitpofready; - card->set_errlog_state = ergo_set_errlog_state; - INIT_WORK(&card->irq_queue, ergo_irq_bh); - spin_lock_init(&card->hysdn_lock); - - return (0); -} /* ergo_inithardware */ diff --git a/drivers/staging/isdn/hysdn/boardergo.h b/drivers/staging/isdn/hysdn/boardergo.h deleted file mode 100644 index e99bd81c4034..000000000000 --- a/drivers/staging/isdn/hysdn/boardergo.h +++ /dev/null @@ -1,100 +0,0 @@ -/* $Id: boardergo.h,v 1.2.6.1 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, definitions for ergo type boards (buffers..). - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - - -/************************************************/ -/* defines for the dual port memory of the card */ -/************************************************/ -#define ERG_DPRAM_PAGE_SIZE 0x2000 /* DPRAM occupies a 8K page */ -#define BOOT_IMG_SIZE 4096 -#define ERG_DPRAM_FILL_SIZE (ERG_DPRAM_PAGE_SIZE - BOOT_IMG_SIZE) - -#define ERG_TO_HY_BUF_SIZE 0x0E00 /* 3072 bytes buffer size to card */ -#define ERG_TO_PC_BUF_SIZE 0x0E00 /* 3072 bytes to PC, too */ - -/* following DPRAM layout copied from OS2-driver boarderg.h */ -typedef struct ErgDpram_tag { - /*0000 */ unsigned char ToHyBuf[ERG_TO_HY_BUF_SIZE]; - /*0E00 */ unsigned char ToPcBuf[ERG_TO_PC_BUF_SIZE]; - - /*1C00 */ unsigned char bSoftUart[SIZE_RSV_SOFT_UART]; - /* size 0x1B0 */ - - /*1DB0 *//* tErrLogEntry */ unsigned char volatile ErrLogMsg[64]; - /* size 64 bytes */ - /*1DB0 unsigned long ulErrType; */ - /*1DB4 unsigned long ulErrSubtype; */ - /*1DB8 unsigned long ucTextSize; */ - /*1DB9 unsigned long ucText[ERRLOG_TEXT_SIZE]; *//* ASCIIZ of len ucTextSize-1 */ - /*1DF0 */ - - /*1DF0 */ unsigned short volatile ToHyChannel; - /*1DF2 */ unsigned short volatile ToHySize; - /*1DF4 */ unsigned char volatile ToHyFlag; - /* !=0: msg for Hy waiting */ - /*1DF5 */ unsigned char volatile ToPcFlag; - /* !=0: msg for PC waiting */ - /*1DF6 */ unsigned short volatile ToPcChannel; - /*1DF8 */ unsigned short volatile ToPcSize; - /*1DFA */ unsigned char bRes1DBA[0x1E00 - 0x1DFA]; - /* 6 bytes */ - - /*1E00 */ unsigned char bRestOfEntryTbl[0x1F00 - 0x1E00]; - /*1F00 */ unsigned long TrapTable[62]; - /*1FF8 */ unsigned char bRes1FF8[0x1FFB - 0x1FF8]; - /* low part of reset vetor */ - /*1FFB */ unsigned char ToPcIntMetro; - /* notes: - * - metro has 32-bit boot ram - accessing - * ToPcInt and ToHyInt would be the same; - * so we moved ToPcInt to 1FFB. - * Because on the PC side both vars are - * readonly (reseting on int from E1 to PC), - * we can read both vars on both cards - * without destroying anything. - * - 1FFB is the high byte of the reset vector, - * so E1 side should NOT change this byte - * when writing! - */ - /*1FFC */ unsigned char volatile ToHyNoDpramErrLog; - /* note: ToHyNoDpramErrLog is used to inform - * boot loader, not to use DPRAM based - * ErrLog; when DOS driver is rewritten - * this becomes obsolete - */ - /*1FFD */ unsigned char bRes1FFD; - /*1FFE */ unsigned char ToPcInt; - /* E1_intclear; on CHAMP2: E1_intset */ - /*1FFF */ unsigned char ToHyInt; - /* E1_intset; on CHAMP2: E1_intclear */ -} tErgDpram; - -/**********************************************/ -/* PCI9050 controller local register offsets: */ -/* copied from boarderg.c */ -/**********************************************/ -#define PCI9050_INTR_REG 0x4C /* Interrupt register */ -#define PCI9050_USER_IO 0x51 /* User I/O register */ - -/* bitmask for PCI9050_INTR_REG: */ -#define PCI9050_INTR_REG_EN1 0x01 /* 1= enable (def.), 0= disable */ -#define PCI9050_INTR_REG_POL1 0x02 /* 1= active high (def.), 0= active low */ -#define PCI9050_INTR_REG_STAT1 0x04 /* 1= intr. active, 0= intr. not active (def.) */ -#define PCI9050_INTR_REG_ENPCI 0x40 /* 1= PCI interrupts enable (def.) */ - -/* bitmask for PCI9050_USER_IO: */ -#define PCI9050_USER_IO_EN3 0x02 /* 1= disable , 0= enable (def.) */ -#define PCI9050_USER_IO_DIR3 0x04 /* 1= output (def.), 0= input */ -#define PCI9050_USER_IO_DAT3 0x08 /* 1= high (def.) , 0= low */ - -#define PCI9050_E1_RESET (PCI9050_USER_IO_DIR3) /* 0x04 */ -#define PCI9050_E1_RUN (PCI9050_USER_IO_DAT3 | PCI9050_USER_IO_DIR3) /* 0x0C */ diff --git a/drivers/staging/isdn/hysdn/hycapi.c b/drivers/staging/isdn/hysdn/hycapi.c deleted file mode 100644 index a2c15cd7bf67..000000000000 --- a/drivers/staging/isdn/hysdn/hycapi.c +++ /dev/null @@ -1,785 +0,0 @@ -/* $Id: hycapi.c,v 1.8.6.4 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, CAPI2.0-Interface. - * - * Author Ulrich Albrecht for Hypercope GmbH - * Copyright 2000 by Hypercope GmbH - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define VER_DRIVER 0 -#define VER_CARDTYPE 1 -#define VER_HWID 2 -#define VER_SERIAL 3 -#define VER_OPTION 4 -#define VER_PROTO 5 -#define VER_PROFILE 6 -#define VER_CAPI 7 - -#include "hysdn_defs.h" -#include - -static char hycapi_revision[] = "$Revision: 1.8.6.4 $"; - -unsigned int hycapi_enable = 0xffffffff; -module_param(hycapi_enable, uint, 0); - -typedef struct _hycapi_appl { - unsigned int ctrl_mask; - capi_register_params rp; - struct sk_buff *listen_req[CAPI_MAXCONTR]; -} hycapi_appl; - -static hycapi_appl hycapi_applications[CAPI_MAXAPPL]; - -static u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); - -static inline int _hycapi_appCheck(int app_id, int ctrl_no) -{ - if ((ctrl_no <= 0) || (ctrl_no > CAPI_MAXCONTR) || (app_id <= 0) || - (app_id > CAPI_MAXAPPL)) - { - printk(KERN_ERR "HYCAPI: Invalid request app_id %d for controller %d", app_id, ctrl_no); - return -1; - } - return ((hycapi_applications[app_id - 1].ctrl_mask & (1 << (ctrl_no-1))) != 0); -} - -/****************************** -Kernel-Capi callback reset_ctr -******************************/ - -static void -hycapi_reset_ctr(struct capi_ctr *ctrl) -{ - hycapictrl_info *cinfo = ctrl->driverdata; - -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "HYCAPI hycapi_reset_ctr\n"); -#endif - capilib_release(&cinfo->ncci_head); - capi_ctr_down(ctrl); -} - -/****************************** -Kernel-Capi callback remove_ctr -******************************/ - -static void -hycapi_remove_ctr(struct capi_ctr *ctrl) -{ - int i; - hycapictrl_info *cinfo = NULL; - hysdn_card *card = NULL; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "HYCAPI hycapi_remove_ctr\n"); -#endif - cinfo = (hycapictrl_info *)(ctrl->driverdata); - if (!cinfo) { - printk(KERN_ERR "No hycapictrl_info set!"); - return; - } - card = cinfo->card; - capi_ctr_suspend_output(ctrl); - for (i = 0; i < CAPI_MAXAPPL; i++) { - if (hycapi_applications[i].listen_req[ctrl->cnr - 1]) { - kfree_skb(hycapi_applications[i].listen_req[ctrl->cnr - 1]); - hycapi_applications[i].listen_req[ctrl->cnr - 1] = NULL; - } - } - detach_capi_ctr(ctrl); - ctrl->driverdata = NULL; - kfree(card->hyctrlinfo); - - - card->hyctrlinfo = NULL; -} - -/*********************************************************** - -Queue a CAPI-message to the controller. - -***********************************************************/ - -static void -hycapi_sendmsg_internal(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); - hysdn_card *card = cinfo->card; - - spin_lock_irq(&cinfo->lock); -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_send_message\n"); -#endif - cinfo->skbs[cinfo->in_idx++] = skb; /* add to buffer list */ - if (cinfo->in_idx >= HYSDN_MAX_CAPI_SKB) - cinfo->in_idx = 0; /* wrap around */ - cinfo->sk_count++; /* adjust counter */ - if (cinfo->sk_count >= HYSDN_MAX_CAPI_SKB) { - /* inform upper layers we're full */ - printk(KERN_ERR "HYSDN Card%d: CAPI-buffer overrun!\n", - card->myid); - capi_ctr_suspend_output(ctrl); - } - cinfo->tx_skb = skb; - spin_unlock_irq(&cinfo->lock); - schedule_work(&card->irq_queue); -} - -/*********************************************************** -hycapi_register_internal - -Send down the CAPI_REGISTER-Command to the controller. -This functions will also be used if the adapter has been rebooted to -re-register any applications in the private list. - -************************************************************/ - -static void -hycapi_register_internal(struct capi_ctr *ctrl, __u16 appl, - capi_register_params *rp) -{ - char ExtFeatureDefaults[] = "49 /0/0/0/0,*/1,*/2,*/3,*/4,*/5,*/6,*/7,*/8,*/9,*"; - hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); - hysdn_card *card = cinfo->card; - struct sk_buff *skb; - __u16 len; - __u8 _command = 0xa0, _subcommand = 0x80; - __u16 MessageNumber = 0x0000; - __u16 MessageBufferSize = 0; - int slen = strlen(ExtFeatureDefaults); -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_register_appl\n"); -#endif - MessageBufferSize = rp->level3cnt * rp->datablkcnt * rp->datablklen; - - len = CAPI_MSG_BASELEN + 8 + slen + 1; - if (!(skb = alloc_skb(len, GFP_ATOMIC))) { - printk(KERN_ERR "HYSDN card%d: memory squeeze in hycapi_register_appl\n", - card->myid); - return; - } - skb_put_data(skb, &len, sizeof(__u16)); - skb_put_data(skb, &appl, sizeof(__u16)); - skb_put_data(skb, &_command, sizeof(__u8)); - skb_put_data(skb, &_subcommand, sizeof(__u8)); - skb_put_data(skb, &MessageNumber, sizeof(__u16)); - skb_put_data(skb, &MessageBufferSize, sizeof(__u16)); - skb_put_data(skb, &(rp->level3cnt), sizeof(__u16)); - skb_put_data(skb, &(rp->datablkcnt), sizeof(__u16)); - skb_put_data(skb, &(rp->datablklen), sizeof(__u16)); - skb_put_data(skb, ExtFeatureDefaults, slen); - hycapi_applications[appl - 1].ctrl_mask |= (1 << (ctrl->cnr - 1)); - hycapi_send_message(ctrl, skb); -} - -/************************************************************ -hycapi_restart_internal - -After an adapter has been rebootet, re-register all applications and -send a LISTEN_REQ (if there has been such a thing ) - -*************************************************************/ - -static void hycapi_restart_internal(struct capi_ctr *ctrl) -{ - int i; - struct sk_buff *skb; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_WARNING "HYSDN: hycapi_restart_internal"); -#endif - for (i = 0; i < CAPI_MAXAPPL; i++) { - if (_hycapi_appCheck(i + 1, ctrl->cnr) == 1) { - hycapi_register_internal(ctrl, i + 1, - &hycapi_applications[i].rp); - if (hycapi_applications[i].listen_req[ctrl->cnr - 1]) { - skb = skb_copy(hycapi_applications[i].listen_req[ctrl->cnr - 1], GFP_ATOMIC); - hycapi_sendmsg_internal(ctrl, skb); - } - } - } -} - -/************************************************************* -Register an application. -Error-checking is done for CAPI-compliance. - -The application is recorded in the internal list. -*************************************************************/ - -static void -hycapi_register_appl(struct capi_ctr *ctrl, __u16 appl, - capi_register_params *rp) -{ - int MaxLogicalConnections = 0, MaxBDataBlocks = 0, MaxBDataLen = 0; - hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); - hysdn_card *card = cinfo->card; - int chk = _hycapi_appCheck(appl, ctrl->cnr); - if (chk < 0) { - return; - } - if (chk == 1) { - printk(KERN_INFO "HYSDN: apl %d already registered\n", appl); - return; - } - MaxBDataBlocks = rp->datablkcnt > CAPI_MAXDATAWINDOW ? CAPI_MAXDATAWINDOW : rp->datablkcnt; - rp->datablkcnt = MaxBDataBlocks; - MaxBDataLen = rp->datablklen < 1024 ? 1024 : rp->datablklen; - rp->datablklen = MaxBDataLen; - - MaxLogicalConnections = rp->level3cnt; - if (MaxLogicalConnections < 0) { - MaxLogicalConnections = card->bchans * -MaxLogicalConnections; - } - if (MaxLogicalConnections == 0) { - MaxLogicalConnections = card->bchans; - } - - rp->level3cnt = MaxLogicalConnections; - memcpy(&hycapi_applications[appl - 1].rp, - rp, sizeof(capi_register_params)); -} - -/********************************************************************* - -hycapi_release_internal - -Send down a CAPI_RELEASE to the controller. -*********************************************************************/ - -static void hycapi_release_internal(struct capi_ctr *ctrl, __u16 appl) -{ - hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); - hysdn_card *card = cinfo->card; - struct sk_buff *skb; - __u16 len; - __u8 _command = 0xa1, _subcommand = 0x80; - __u16 MessageNumber = 0x0000; - - capilib_release_appl(&cinfo->ncci_head, appl); - -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_release_appl\n"); -#endif - len = CAPI_MSG_BASELEN; - if (!(skb = alloc_skb(len, GFP_ATOMIC))) { - printk(KERN_ERR "HYSDN card%d: memory squeeze in hycapi_register_appl\n", - card->myid); - return; - } - skb_put_data(skb, &len, sizeof(__u16)); - skb_put_data(skb, &appl, sizeof(__u16)); - skb_put_data(skb, &_command, sizeof(__u8)); - skb_put_data(skb, &_subcommand, sizeof(__u8)); - skb_put_data(skb, &MessageNumber, sizeof(__u16)); - hycapi_send_message(ctrl, skb); - hycapi_applications[appl - 1].ctrl_mask &= ~(1 << (ctrl->cnr - 1)); -} - -/****************************************************************** -hycapi_release_appl - -Release the application from the internal list an remove it's -registration at controller-level -******************************************************************/ - -static void -hycapi_release_appl(struct capi_ctr *ctrl, __u16 appl) -{ - int chk; - - chk = _hycapi_appCheck(appl, ctrl->cnr); - if (chk < 0) { - printk(KERN_ERR "HYCAPI: Releasing invalid appl %d on controller %d\n", appl, ctrl->cnr); - return; - } - if (hycapi_applications[appl - 1].listen_req[ctrl->cnr - 1]) { - kfree_skb(hycapi_applications[appl - 1].listen_req[ctrl->cnr - 1]); - hycapi_applications[appl - 1].listen_req[ctrl->cnr - 1] = NULL; - } - if (chk == 1) - { - hycapi_release_internal(ctrl, appl); - } -} - - -/************************************************************** -Kill a single controller. -**************************************************************/ - -int hycapi_capi_release(hysdn_card *card) -{ - hycapictrl_info *cinfo = card->hyctrlinfo; - struct capi_ctr *ctrl; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_capi_release\n"); -#endif - if (cinfo) { - ctrl = &cinfo->capi_ctrl; - hycapi_remove_ctr(ctrl); - } - return 0; -} - -/************************************************************** -hycapi_capi_stop - -Stop CAPI-Output on a card. (e.g. during reboot) -***************************************************************/ - -int hycapi_capi_stop(hysdn_card *card) -{ - hycapictrl_info *cinfo = card->hyctrlinfo; - struct capi_ctr *ctrl; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_capi_stop\n"); -#endif - if (cinfo) { - ctrl = &cinfo->capi_ctrl; -/* ctrl->suspend_output(ctrl); */ - capi_ctr_down(ctrl); - } - return 0; -} - -/*************************************************************** -hycapi_send_message - -Send a message to the controller. - -Messages are parsed for their Command/Subcommand-type, and appropriate -action's are performed. - -Note that we have to muck around with a 64Bit-DATA_REQ as there are -firmware-releases that do not check the MsgLen-Indication! - -***************************************************************/ - -static u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - __u16 appl_id; - int _len, _len2; - __u8 msghead[64]; - hycapictrl_info *cinfo = ctrl->driverdata; - u16 retval = CAPI_NOERROR; - - appl_id = CAPIMSG_APPID(skb->data); - switch (_hycapi_appCheck(appl_id, ctrl->cnr)) - { - case 0: -/* printk(KERN_INFO "Need to register\n"); */ - hycapi_register_internal(ctrl, - appl_id, - &(hycapi_applications[appl_id - 1].rp)); - break; - case 1: - break; - default: - printk(KERN_ERR "HYCAPI: Controller mixup!\n"); - retval = CAPI_ILLAPPNR; - goto out; - } - switch (CAPIMSG_CMD(skb->data)) { - case CAPI_DISCONNECT_B3_RESP: - capilib_free_ncci(&cinfo->ncci_head, appl_id, - CAPIMSG_NCCI(skb->data)); - break; - case CAPI_DATA_B3_REQ: - _len = CAPIMSG_LEN(skb->data); - if (_len > 22) { - _len2 = _len - 22; - skb_copy_from_linear_data(skb, msghead, 22); - skb_copy_to_linear_data_offset(skb, _len2, - msghead, 22); - skb_pull(skb, _len2); - CAPIMSG_SETLEN(skb->data, 22); - retval = capilib_data_b3_req(&cinfo->ncci_head, - CAPIMSG_APPID(skb->data), - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - } - break; - case CAPI_LISTEN_REQ: - if (hycapi_applications[appl_id - 1].listen_req[ctrl->cnr - 1]) - { - kfree_skb(hycapi_applications[appl_id - 1].listen_req[ctrl->cnr - 1]); - hycapi_applications[appl_id - 1].listen_req[ctrl->cnr - 1] = NULL; - } - if (!(hycapi_applications[appl_id -1].listen_req[ctrl->cnr - 1] = skb_copy(skb, GFP_ATOMIC))) - { - printk(KERN_ERR "HYSDN: memory squeeze in private_listen\n"); - } - break; - default: - break; - } -out: - if (retval == CAPI_NOERROR) - hycapi_sendmsg_internal(ctrl, skb); - else - dev_kfree_skb_any(skb); - - return retval; -} - -static int hycapi_proc_show(struct seq_file *m, void *v) -{ - struct capi_ctr *ctrl = m->private; - hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); - hysdn_card *card = cinfo->card; - char *s; - - seq_printf(m, "%-16s %s\n", "name", cinfo->cardname); - seq_printf(m, "%-16s 0x%x\n", "io", card->iobase); - seq_printf(m, "%-16s %d\n", "irq", card->irq); - - switch (card->brdtype) { - case BD_PCCARD: s = "HYSDN Hycard"; break; - case BD_ERGO: s = "HYSDN Ergo2"; break; - case BD_METRO: s = "HYSDN Metro4"; break; - case BD_CHAMP2: s = "HYSDN Champ2"; break; - case BD_PLEXUS: s = "HYSDN Plexus30"; break; - default: s = "???"; break; - } - seq_printf(m, "%-16s %s\n", "type", s); - if ((s = cinfo->version[VER_DRIVER]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_driver", s); - if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_cardtype", s); - if ((s = cinfo->version[VER_SERIAL]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_serial", s); - - seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); - - return 0; -} - -/************************************************************** -hycapi_load_firmware - -This does NOT load any firmware, but the callback somehow is needed -on capi-interface registration. - -**************************************************************/ - -static int hycapi_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_load_firmware\n"); -#endif - return 0; -} - - -static char *hycapi_procinfo(struct capi_ctr *ctrl) -{ - hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "%s\n", __func__); -#endif - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d %s", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->iobase : 0x0, - cinfo->card ? cinfo->card->irq : 0, - hycapi_revision - ); - return cinfo->infobuf; -} - -/****************************************************************** -hycapi_rx_capipkt - -Receive a capi-message. - -All B3_DATA_IND are converted to 64K-extension compatible format. -New nccis are created if necessary. -*******************************************************************/ - -void -hycapi_rx_capipkt(hysdn_card *card, unsigned char *buf, unsigned short len) -{ - struct sk_buff *skb; - hycapictrl_info *cinfo = card->hyctrlinfo; - struct capi_ctr *ctrl; - __u16 ApplId; - __u16 MsgLen, info; - __u16 len2, CapiCmd; - __u32 CP64[2] = {0, 0}; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_rx_capipkt\n"); -#endif - if (!cinfo) { - return; - } - ctrl = &cinfo->capi_ctrl; - if (len < CAPI_MSG_BASELEN) { - printk(KERN_ERR "HYSDN Card%d: invalid CAPI-message, length %d!\n", - card->myid, len); - return; - } - MsgLen = CAPIMSG_LEN(buf); - ApplId = CAPIMSG_APPID(buf); - CapiCmd = CAPIMSG_CMD(buf); - - if ((CapiCmd == CAPI_DATA_B3_IND) && (MsgLen < 30)) { - len2 = len + (30 - MsgLen); - if (!(skb = alloc_skb(len2, GFP_ATOMIC))) { - printk(KERN_ERR "HYSDN Card%d: incoming packet dropped\n", - card->myid); - return; - } - skb_put_data(skb, buf, MsgLen); - skb_put_data(skb, CP64, 2 * sizeof(__u32)); - skb_put_data(skb, buf + MsgLen, len - MsgLen); - CAPIMSG_SETLEN(skb->data, 30); - } else { - if (!(skb = alloc_skb(len, GFP_ATOMIC))) { - printk(KERN_ERR "HYSDN Card%d: incoming packet dropped\n", - card->myid); - return; - } - skb_put_data(skb, buf, len); - } - switch (CAPIMSG_CMD(skb->data)) - { - case CAPI_CONNECT_B3_CONF: -/* Check info-field for error-indication: */ - info = CAPIMSG_U16(skb->data, 12); - switch (info) - { - case 0: - capilib_new_ncci(&cinfo->ncci_head, ApplId, CAPIMSG_NCCI(skb->data), - hycapi_applications[ApplId - 1].rp.datablkcnt); - - break; - case 0x0001: - printk(KERN_ERR "HYSDN Card%d: NCPI not supported by current " - "protocol. NCPI ignored.\n", card->myid); - break; - case 0x2001: - printk(KERN_ERR "HYSDN Card%d: Message not supported in" - " current state\n", card->myid); - break; - case 0x2002: - printk(KERN_ERR "HYSDN Card%d: invalid PLCI\n", card->myid); - break; - case 0x2004: - printk(KERN_ERR "HYSDN Card%d: out of NCCI\n", card->myid); - break; - case 0x3008: - printk(KERN_ERR "HYSDN Card%d: NCPI not supported\n", - card->myid); - break; - default: - printk(KERN_ERR "HYSDN Card%d: Info in CONNECT_B3_CONF: %d\n", - card->myid, info); - break; - } - break; - case CAPI_CONNECT_B3_IND: - capilib_new_ncci(&cinfo->ncci_head, ApplId, - CAPIMSG_NCCI(skb->data), - hycapi_applications[ApplId - 1].rp.datablkcnt); - break; - case CAPI_DATA_B3_CONF: - capilib_data_b3_conf(&cinfo->ncci_head, ApplId, - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - break; - default: - break; - } - capi_ctr_handle_message(ctrl, ApplId, skb); -} - -/****************************************************************** -hycapi_tx_capiack - -Internally acknowledge a msg sent. This will remove the msg from the -internal queue. - -*******************************************************************/ - -void hycapi_tx_capiack(hysdn_card *card) -{ - hycapictrl_info *cinfo = card->hyctrlinfo; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_tx_capiack\n"); -#endif - if (!cinfo) { - return; - } - spin_lock_irq(&cinfo->lock); - kfree_skb(cinfo->skbs[cinfo->out_idx]); /* free skb */ - cinfo->skbs[cinfo->out_idx++] = NULL; - if (cinfo->out_idx >= HYSDN_MAX_CAPI_SKB) - cinfo->out_idx = 0; /* wrap around */ - - if (cinfo->sk_count-- == HYSDN_MAX_CAPI_SKB) /* dec usage count */ - capi_ctr_resume_output(&cinfo->capi_ctrl); - spin_unlock_irq(&cinfo->lock); -} - -/*************************************************************** -hycapi_tx_capiget(hysdn_card *card) - -This is called when polling for messages to SEND. - -****************************************************************/ - -struct sk_buff * -hycapi_tx_capiget(hysdn_card *card) -{ - hycapictrl_info *cinfo = card->hyctrlinfo; - if (!cinfo) { - return (struct sk_buff *)NULL; - } - if (!cinfo->sk_count) - return (struct sk_buff *)NULL; /* nothing available */ - - return (cinfo->skbs[cinfo->out_idx]); /* next packet to send */ -} - - -/********************************************************** -int hycapi_init() - -attach the capi-driver to the kernel-capi. - -***********************************************************/ - -int hycapi_init(void) -{ - int i; - for (i = 0; i < CAPI_MAXAPPL; i++) { - memset(&(hycapi_applications[i]), 0, sizeof(hycapi_appl)); - } - return (0); -} - -/************************************************************** -hycapi_cleanup(void) - -detach the capi-driver to the kernel-capi. Actually this should -free some more ressources. Do that later. -**************************************************************/ - -void -hycapi_cleanup(void) -{ -} - -/******************************************************************** -hycapi_capi_create(hysdn_card *card) - -Attach the card with its capi-ctrl. -*********************************************************************/ - -static void hycapi_fill_profile(hysdn_card *card) -{ - hycapictrl_info *cinfo = NULL; - struct capi_ctr *ctrl = NULL; - cinfo = card->hyctrlinfo; - if (!cinfo) return; - ctrl = &cinfo->capi_ctrl; - strcpy(ctrl->manu, "Hypercope"); - ctrl->version.majorversion = 2; - ctrl->version.minorversion = 0; - ctrl->version.majormanuversion = 3; - ctrl->version.minormanuversion = 2; - ctrl->profile.ncontroller = card->myid; - ctrl->profile.nbchannel = card->bchans; - ctrl->profile.goptions = GLOBAL_OPTION_INTERNAL_CONTROLLER | - GLOBAL_OPTION_B_CHANNEL_OPERATION; - ctrl->profile.support1 = B1_PROT_64KBIT_HDLC | - (card->faxchans ? B1_PROT_T30 : 0) | - B1_PROT_64KBIT_TRANSPARENT; - ctrl->profile.support2 = B2_PROT_ISO7776 | - (card->faxchans ? B2_PROT_T30 : 0) | - B2_PROT_TRANSPARENT; - ctrl->profile.support3 = B3_PROT_TRANSPARENT | - B3_PROT_T90NL | - (card->faxchans ? B3_PROT_T30 : 0) | - (card->faxchans ? B3_PROT_T30EXT : 0) | - B3_PROT_ISO8208; -} - -int -hycapi_capi_create(hysdn_card *card) -{ - hycapictrl_info *cinfo = NULL; - struct capi_ctr *ctrl = NULL; - int retval; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_capi_create\n"); -#endif - if ((hycapi_enable & (1 << card->myid)) == 0) { - return 1; - } - if (!card->hyctrlinfo) { - cinfo = kzalloc(sizeof(hycapictrl_info), GFP_ATOMIC); - if (!cinfo) { - printk(KERN_WARNING "HYSDN: no memory for capi-ctrl.\n"); - return -ENOMEM; - } - card->hyctrlinfo = cinfo; - cinfo->card = card; - spin_lock_init(&cinfo->lock); - INIT_LIST_HEAD(&cinfo->ncci_head); - - switch (card->brdtype) { - case BD_PCCARD: strcpy(cinfo->cardname, "HYSDN Hycard"); break; - case BD_ERGO: strcpy(cinfo->cardname, "HYSDN Ergo2"); break; - case BD_METRO: strcpy(cinfo->cardname, "HYSDN Metro4"); break; - case BD_CHAMP2: strcpy(cinfo->cardname, "HYSDN Champ2"); break; - case BD_PLEXUS: strcpy(cinfo->cardname, "HYSDN Plexus30"); break; - default: strcpy(cinfo->cardname, "HYSDN ???"); break; - } - - ctrl = &cinfo->capi_ctrl; - ctrl->driver_name = "hycapi"; - ctrl->driverdata = cinfo; - ctrl->register_appl = hycapi_register_appl; - ctrl->release_appl = hycapi_release_appl; - ctrl->send_message = hycapi_send_message; - ctrl->load_firmware = hycapi_load_firmware; - ctrl->reset_ctr = hycapi_reset_ctr; - ctrl->procinfo = hycapi_procinfo; - ctrl->proc_show = hycapi_proc_show; - strcpy(ctrl->name, cinfo->cardname); - ctrl->owner = THIS_MODULE; - - retval = attach_capi_ctr(ctrl); - if (retval) { - printk(KERN_ERR "hycapi: attach controller failed.\n"); - return -EBUSY; - } - /* fill in the blanks: */ - hycapi_fill_profile(card); - capi_ctr_ready(ctrl); - } else { - /* resume output on stopped ctrl */ - ctrl = &card->hyctrlinfo->capi_ctrl; - hycapi_fill_profile(card); - capi_ctr_ready(ctrl); - hycapi_restart_internal(ctrl); -/* ctrl->resume_output(ctrl); */ - } - return 0; -} diff --git a/drivers/staging/isdn/hysdn/hysdn_boot.c b/drivers/staging/isdn/hysdn/hysdn_boot.c deleted file mode 100644 index ba177c3a621b..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_boot.c +++ /dev/null @@ -1,400 +0,0 @@ -/* $Id: hysdn_boot.c,v 1.4.6.4 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards - * specific routines for booting and pof handling - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include - -#include "hysdn_defs.h" -#include "hysdn_pof.h" - -/********************************/ -/* defines for pof read handler */ -/********************************/ -#define POF_READ_FILE_HEAD 0 -#define POF_READ_TAG_HEAD 1 -#define POF_READ_TAG_DATA 2 - -/************************************************************/ -/* definition of boot specific data area. This data is only */ -/* needed during boot and so allocated dynamically. */ -/************************************************************/ -struct boot_data { - unsigned short Cryptor; /* for use with Decrypt function */ - unsigned short Nrecs; /* records remaining in file */ - unsigned char pof_state;/* actual state of read handler */ - unsigned char is_crypted;/* card data is crypted */ - int BufSize; /* actual number of bytes bufferd */ - int last_error; /* last occurred error */ - unsigned short pof_recid;/* actual pof recid */ - unsigned long pof_reclen;/* total length of pof record data */ - unsigned long pof_recoffset;/* actual offset inside pof record */ - union { - unsigned char BootBuf[BOOT_BUF_SIZE];/* buffer as byte count */ - tPofRecHdr PofRecHdr; /* header for actual record/chunk */ - tPofFileHdr PofFileHdr; /* header from POF file */ - tPofTimeStamp PofTime; /* time information */ - } buf; -}; - -/*****************************************************/ -/* start decryption of successive POF file chuncks. */ -/* */ -/* to be called at start of POF file reading, */ -/* before starting any decryption on any POF record. */ -/*****************************************************/ -static void -StartDecryption(struct boot_data *boot) -{ - boot->Cryptor = CRYPT_STARTTERM; -} /* StartDecryption */ - - -/***************************************************************/ -/* decrypt complete BootBuf */ -/* NOTE: decryption must be applied to all or none boot tags - */ -/* to HI and LO boot loader and (all) seq tags, because */ -/* global Cryptor is started for whole POF. */ -/***************************************************************/ -static void -DecryptBuf(struct boot_data *boot, int cnt) -{ - unsigned char *bufp = boot->buf.BootBuf; - - while (cnt--) { - boot->Cryptor = (boot->Cryptor >> 1) ^ ((boot->Cryptor & 1U) ? CRYPT_FEEDTERM : 0); - *bufp++ ^= (unsigned char)boot->Cryptor; - } -} /* DecryptBuf */ - -/********************************************************************************/ -/* pof_handle_data executes the required actions dependent on the active record */ -/* id. If successful 0 is returned, a negative value shows an error. */ -/********************************************************************************/ -static int -pof_handle_data(hysdn_card *card, int datlen) -{ - struct boot_data *boot = card->boot; /* pointer to boot specific data */ - long l; - unsigned char *imgp; - int img_len; - - /* handle the different record types */ - switch (boot->pof_recid) { - - case TAG_TIMESTMP: - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF created %s", boot->buf.PofTime.DateTimeText); - break; - - case TAG_CBOOTDTA: - DecryptBuf(boot, datlen); /* we need to encrypt the buffer */ - /* fall through */ - case TAG_BOOTDTA: - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF got %s len=%d offs=0x%lx", - (boot->pof_recid == TAG_CBOOTDTA) ? "CBOOTDATA" : "BOOTDTA", - datlen, boot->pof_recoffset); - - if (boot->pof_reclen != POF_BOOT_LOADER_TOTAL_SIZE) { - boot->last_error = EPOF_BAD_IMG_SIZE; /* invalid length */ - return (boot->last_error); - } - imgp = boot->buf.BootBuf; /* start of buffer */ - img_len = datlen; /* maximum length to transfer */ - - l = POF_BOOT_LOADER_OFF_IN_PAGE - - (boot->pof_recoffset & (POF_BOOT_LOADER_PAGE_SIZE - 1)); - if (l > 0) { - /* buffer needs to be truncated */ - imgp += l; /* advance pointer */ - img_len -= l; /* adjust len */ - } - /* at this point no special handling for data wrapping over buffer */ - /* is necessary, because the boot image always will be adjusted to */ - /* match a page boundary inside the buffer. */ - /* The buffer for the boot image on the card is filled in 2 cycles */ - /* first the 1024 hi-words are put in the buffer, then the low 1024 */ - /* word are handled in the same way with different offset. */ - - if (img_len > 0) { - /* data available for copy */ - if ((boot->last_error = - card->writebootimg(card, imgp, - (boot->pof_recoffset > POF_BOOT_LOADER_PAGE_SIZE) ? 2 : 0)) < 0) - return (boot->last_error); - } - break; /* end of case boot image hi/lo */ - - case TAG_CABSDATA: - DecryptBuf(boot, datlen); /* we need to encrypt the buffer */ - /* fall through */ - case TAG_ABSDATA: - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF got %s len=%d offs=0x%lx", - (boot->pof_recid == TAG_CABSDATA) ? "CABSDATA" : "ABSDATA", - datlen, boot->pof_recoffset); - - if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen)) < 0) - return (boot->last_error); /* error writing data */ - - if (boot->pof_recoffset + datlen >= boot->pof_reclen) - return (card->waitpofready(card)); /* data completely spooled, wait for ready */ - - break; /* end of case boot seq data */ - - default: - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF got data(id=0x%lx) len=%d offs=0x%lx", boot->pof_recid, - datlen, boot->pof_recoffset); - - break; /* simply skip record */ - } /* switch boot->pof_recid */ - - return (0); -} /* pof_handle_data */ - - -/******************************************************************************/ -/* pof_write_buffer is called when the buffer has been filled with the needed */ -/* number of data bytes. The number delivered is additionally supplied for */ -/* verification. The functions handles the data and returns the needed number */ -/* of bytes for the next action. If the returned value is 0 or less an error */ -/* occurred and booting must be aborted. */ -/******************************************************************************/ -int -pof_write_buffer(hysdn_card *card, int datlen) -{ - struct boot_data *boot = card->boot; /* pointer to boot specific data */ - - if (!boot) - return (-EFAULT); /* invalid call */ - if (boot->last_error < 0) - return (boot->last_error); /* repeated error */ - - if (card->debug_flags & LOG_POF_WRITE) - hysdn_addlog(card, "POF write: got %d bytes ", datlen); - - switch (boot->pof_state) { - case POF_READ_FILE_HEAD: - if (card->debug_flags & LOG_POF_WRITE) - hysdn_addlog(card, "POF write: checking file header"); - - if (datlen != sizeof(tPofFileHdr)) { - boot->last_error = -EPOF_INTERNAL; - break; - } - if (boot->buf.PofFileHdr.Magic != TAGFILEMAGIC) { - boot->last_error = -EPOF_BAD_MAGIC; - break; - } - /* Setup the new state and vars */ - boot->Nrecs = (unsigned short)(boot->buf.PofFileHdr.N_PofRecs); /* limited to 65535 */ - boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */ - boot->last_error = sizeof(tPofRecHdr); /* new length */ - break; - - case POF_READ_TAG_HEAD: - if (card->debug_flags & LOG_POF_WRITE) - hysdn_addlog(card, "POF write: checking tag header"); - - if (datlen != sizeof(tPofRecHdr)) { - boot->last_error = -EPOF_INTERNAL; - break; - } - boot->pof_recid = boot->buf.PofRecHdr.PofRecId; /* actual pof recid */ - boot->pof_reclen = boot->buf.PofRecHdr.PofRecDataLen; /* total length */ - boot->pof_recoffset = 0; /* no starting offset */ - - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF: got record id=0x%lx length=%ld ", - boot->pof_recid, boot->pof_reclen); - - boot->pof_state = POF_READ_TAG_DATA; /* now start with tag data */ - if (boot->pof_reclen < BOOT_BUF_SIZE) - boot->last_error = boot->pof_reclen; /* limit size */ - else - boot->last_error = BOOT_BUF_SIZE; /* maximum */ - - if (!boot->last_error) { /* no data inside record */ - boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */ - boot->last_error = sizeof(tPofRecHdr); /* new length */ - } - break; - - case POF_READ_TAG_DATA: - if (card->debug_flags & LOG_POF_WRITE) - hysdn_addlog(card, "POF write: getting tag data"); - - if (datlen != boot->last_error) { - boot->last_error = -EPOF_INTERNAL; - break; - } - if ((boot->last_error = pof_handle_data(card, datlen)) < 0) - return (boot->last_error); /* an error occurred */ - boot->pof_recoffset += datlen; - if (boot->pof_recoffset >= boot->pof_reclen) { - boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */ - boot->last_error = sizeof(tPofRecHdr); /* new length */ - } else { - if (boot->pof_reclen - boot->pof_recoffset < BOOT_BUF_SIZE) - boot->last_error = boot->pof_reclen - boot->pof_recoffset; /* limit size */ - else - boot->last_error = BOOT_BUF_SIZE; /* maximum */ - } - break; - - default: - boot->last_error = -EPOF_INTERNAL; /* unknown state */ - break; - } /* switch (boot->pof_state) */ - - return (boot->last_error); -} /* pof_write_buffer */ - - -/*******************************************************************************/ -/* pof_write_open is called when an open for boot on the cardlog device occurs. */ -/* The function returns the needed number of bytes for the next operation. If */ -/* the returned number is less or equal 0 an error specified by this code */ -/* occurred. Additionally the pointer to the buffer data area is set on success */ -/*******************************************************************************/ -int -pof_write_open(hysdn_card *card, unsigned char **bufp) -{ - struct boot_data *boot; /* pointer to boot specific data */ - - if (card->boot) { - if (card->debug_flags & LOG_POF_OPEN) - hysdn_addlog(card, "POF open: already opened for boot"); - return (-ERR_ALREADY_BOOT); /* boot already active */ - } - /* error no mem available */ - if (!(boot = kzalloc(sizeof(struct boot_data), GFP_KERNEL))) { - if (card->debug_flags & LOG_MEM_ERR) - hysdn_addlog(card, "POF open: unable to allocate mem"); - return (-EFAULT); - } - card->boot = boot; - card->state = CARD_STATE_BOOTING; - - card->stopcard(card); /* first stop the card */ - if (card->testram(card)) { - if (card->debug_flags & LOG_POF_OPEN) - hysdn_addlog(card, "POF open: DPRAM test failure"); - boot->last_error = -ERR_BOARD_DPRAM; - card->state = CARD_STATE_BOOTERR; /* show boot error */ - return (boot->last_error); - } - boot->BufSize = 0; /* Buffer is empty */ - boot->pof_state = POF_READ_FILE_HEAD; /* read file header */ - StartDecryption(boot); /* if POF File should be encrypted */ - - if (card->debug_flags & LOG_POF_OPEN) - hysdn_addlog(card, "POF open: success"); - - *bufp = boot->buf.BootBuf; /* point to buffer */ - return (sizeof(tPofFileHdr)); -} /* pof_write_open */ - -/********************************************************************************/ -/* pof_write_close is called when an close of boot on the cardlog device occurs. */ -/* The return value must be 0 if everything has happened as desired. */ -/********************************************************************************/ -int -pof_write_close(hysdn_card *card) -{ - struct boot_data *boot = card->boot; /* pointer to boot specific data */ - - if (!boot) - return (-EFAULT); /* invalid call */ - - card->boot = NULL; /* no boot active */ - kfree(boot); - - if (card->state == CARD_STATE_RUN) - card->set_errlog_state(card, 1); /* activate error log */ - - if (card->debug_flags & LOG_POF_OPEN) - hysdn_addlog(card, "POF close: success"); - - return (0); -} /* pof_write_close */ - -/*********************************************************************************/ -/* EvalSysrTokData checks additional records delivered with the Sysready Message */ -/* when POF has been booted. A return value of 0 is used if no error occurred. */ -/*********************************************************************************/ -int -EvalSysrTokData(hysdn_card *card, unsigned char *cp, int len) -{ - u_char *p; - u_char crc; - - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "SysReady Token data length %d", len); - - if (len < 2) { - hysdn_addlog(card, "SysReady Token Data to short"); - return (1); - } - for (p = cp, crc = 0; p < (cp + len - 2); p++) - if ((crc & 0x80)) - crc = (((u_char) (crc << 1)) + 1) + *p; - else - crc = ((u_char) (crc << 1)) + *p; - crc = ~crc; - if (crc != *(cp + len - 1)) { - hysdn_addlog(card, "SysReady Token Data invalid CRC"); - return (1); - } - len--; /* don't check CRC byte */ - while (len > 0) { - - if (*cp == SYSR_TOK_END) - return (0); /* End of Token stream */ - - if (len < (*(cp + 1) + 2)) { - hysdn_addlog(card, "token 0x%x invalid length %d", *cp, *(cp + 1)); - return (1); - } - switch (*cp) { - case SYSR_TOK_B_CHAN: /* 1 */ - if (*(cp + 1) != 1) - return (1); /* length invalid */ - card->bchans = *(cp + 2); - break; - - case SYSR_TOK_FAX_CHAN: /* 2 */ - if (*(cp + 1) != 1) - return (1); /* length invalid */ - card->faxchans = *(cp + 2); - break; - - case SYSR_TOK_MAC_ADDR: /* 3 */ - if (*(cp + 1) != 6) - return (1); /* length invalid */ - memcpy(card->mac_addr, cp + 2, 6); - break; - - default: - hysdn_addlog(card, "unknown token 0x%02x length %d", *cp, *(cp + 1)); - break; - } - len -= (*(cp + 1) + 2); /* adjust len */ - cp += (*(cp + 1) + 2); /* and pointer */ - } - - hysdn_addlog(card, "no end token found"); - return (1); -} /* EvalSysrTokData */ diff --git a/drivers/staging/isdn/hysdn/hysdn_defs.h b/drivers/staging/isdn/hysdn/hysdn_defs.h deleted file mode 100644 index cdac46a21692..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_defs.h +++ /dev/null @@ -1,282 +0,0 @@ -/* $Id: hysdn_defs.h,v 1.5.6.3 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards - * global definitions and exported vars and functions. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#ifndef HYSDN_DEFS_H -#define HYSDN_DEFS_H - -#include -#include -#include -#include - -#include "ince1pc.h" - -#ifdef CONFIG_HYSDN_CAPI -#include -#include -#include -#include - -/***************************/ -/* CAPI-Profile values. */ -/***************************/ - -#define GLOBAL_OPTION_INTERNAL_CONTROLLER 0x0001 -#define GLOBAL_OPTION_EXTERNAL_CONTROLLER 0x0002 -#define GLOBAL_OPTION_HANDSET 0x0004 -#define GLOBAL_OPTION_DTMF 0x0008 -#define GLOBAL_OPTION_SUPPL_SERVICES 0x0010 -#define GLOBAL_OPTION_CHANNEL_ALLOCATION 0x0020 -#define GLOBAL_OPTION_B_CHANNEL_OPERATION 0x0040 - -#define B1_PROT_64KBIT_HDLC 0x0001 -#define B1_PROT_64KBIT_TRANSPARENT 0x0002 -#define B1_PROT_V110_ASYNCH 0x0004 -#define B1_PROT_V110_SYNCH 0x0008 -#define B1_PROT_T30 0x0010 -#define B1_PROT_64KBIT_INV_HDLC 0x0020 -#define B1_PROT_56KBIT_TRANSPARENT 0x0040 - -#define B2_PROT_ISO7776 0x0001 -#define B2_PROT_TRANSPARENT 0x0002 -#define B2_PROT_SDLC 0x0004 -#define B2_PROT_LAPD 0x0008 -#define B2_PROT_T30 0x0010 -#define B2_PROT_PPP 0x0020 -#define B2_PROT_TRANSPARENT_IGNORE_B1_FRAMING_ERRORS 0x0040 - -#define B3_PROT_TRANSPARENT 0x0001 -#define B3_PROT_T90NL 0x0002 -#define B3_PROT_ISO8208 0x0004 -#define B3_PROT_X25_DCE 0x0008 -#define B3_PROT_T30 0x0010 -#define B3_PROT_T30EXT 0x0020 - -#define HYSDN_MAXVERSION 8 - -/* Number of sendbuffers in CAPI-queue */ -#define HYSDN_MAX_CAPI_SKB 20 - -#endif /* CONFIG_HYSDN_CAPI*/ - -/************************************************/ -/* constants and bits for debugging/log outputs */ -/************************************************/ -#define LOG_MAX_LINELEN 120 -#define DEB_OUT_SYSLOG 0x80000000 /* output to syslog instead of proc fs */ -#define LOG_MEM_ERR 0x00000001 /* log memory errors like kmalloc failure */ -#define LOG_POF_OPEN 0x00000010 /* log pof open and close activities */ -#define LOG_POF_RECORD 0x00000020 /* log pof record parser */ -#define LOG_POF_WRITE 0x00000040 /* log detailed pof write operation */ -#define LOG_POF_CARD 0x00000080 /* log pof related card functions */ -#define LOG_CNF_LINE 0x00000100 /* all conf lines are put to procfs */ -#define LOG_CNF_DATA 0x00000200 /* non comment conf lines are shown with channel */ -#define LOG_CNF_MISC 0x00000400 /* additional conf line debug outputs */ -#define LOG_SCHED_ASYN 0x00001000 /* debug schedulers async tx routines */ -#define LOG_PROC_OPEN 0x00100000 /* open and close from procfs are logged */ -#define LOG_PROC_ALL 0x00200000 /* all actions from procfs are logged */ -#define LOG_NET_INIT 0x00010000 /* network init and deinit logging */ - -#define DEF_DEB_FLAGS 0x7fff000f /* everything is logged to procfs */ - -/**********************************/ -/* proc filesystem name constants */ -/**********************************/ -#define PROC_SUBDIR_NAME "hysdn" -#define PROC_CONF_BASENAME "cardconf" -#define PROC_LOG_BASENAME "cardlog" - -/***********************************/ -/* PCI 32 bit parms for IO and MEM */ -/***********************************/ -#define PCI_REG_PLX_MEM_BASE 0 -#define PCI_REG_PLX_IO_BASE 1 -#define PCI_REG_MEMORY_BASE 3 - -/**************/ -/* card types */ -/**************/ -#define BD_NONE 0U -#define BD_PERFORMANCE 1U -#define BD_VALUE 2U -#define BD_PCCARD 3U -#define BD_ERGO 4U -#define BD_METRO 5U -#define BD_CHAMP2 6U -#define BD_PLEXUS 7U - -/******************************************************/ -/* defined states for cards shown by reading cardconf */ -/******************************************************/ -#define CARD_STATE_UNUSED 0 /* never been used or booted */ -#define CARD_STATE_BOOTING 1 /* booting is in progress */ -#define CARD_STATE_BOOTERR 2 /* a previous boot was aborted */ -#define CARD_STATE_RUN 3 /* card is active */ - -/*******************************/ -/* defines for error_log_state */ -/*******************************/ -#define ERRLOG_STATE_OFF 0 /* error log is switched off, nothing to do */ -#define ERRLOG_STATE_ON 1 /* error log is switched on, wait for data */ -#define ERRLOG_STATE_START 2 /* start error logging */ -#define ERRLOG_STATE_STOP 3 /* stop error logging */ - -/*******************************/ -/* data structure for one card */ -/*******************************/ -typedef struct HYSDN_CARD { - - /* general variables for the cards */ - int myid; /* own driver card id */ - unsigned char bus; /* pci bus the card is connected to */ - unsigned char devfn; /* slot+function bit encoded */ - unsigned short subsysid;/* PCI subsystem id */ - unsigned char brdtype; /* type of card */ - unsigned int bchans; /* number of available B-channels */ - unsigned int faxchans; /* number of available fax-channels */ - unsigned char mac_addr[6];/* MAC Address read from card */ - unsigned int irq; /* interrupt number */ - unsigned int iobase; /* IO-port base address */ - unsigned long plxbase; /* PLX memory base */ - unsigned long membase; /* DPRAM memory base */ - unsigned long memend; /* DPRAM memory end */ - void *dpram; /* mapped dpram */ - int state; /* actual state of card -> CARD_STATE_** */ - struct HYSDN_CARD *next; /* pointer to next card */ - - /* data areas for the /proc file system */ - void *proclog; /* pointer to proclog filesystem specific data */ - void *procconf; /* pointer to procconf filesystem specific data */ - - /* debugging and logging */ - unsigned char err_log_state;/* actual error log state of the card */ - unsigned long debug_flags;/* tells what should be debugged and where */ - void (*set_errlog_state) (struct HYSDN_CARD *, int); - - /* interrupt handler + interrupt synchronisation */ - struct work_struct irq_queue; /* interrupt task queue */ - unsigned char volatile irq_enabled;/* interrupt enabled if != 0 */ - unsigned char volatile hw_lock;/* hardware is currently locked -> no access */ - - /* boot process */ - void *boot; /* pointer to boot private data */ - int (*writebootimg) (struct HYSDN_CARD *, unsigned char *, unsigned long); - int (*writebootseq) (struct HYSDN_CARD *, unsigned char *, int); - int (*waitpofready) (struct HYSDN_CARD *); - int (*testram) (struct HYSDN_CARD *); - - /* scheduler for data transfer (only async parts) */ - unsigned char async_data[256];/* async data to be sent (normally for config) */ - unsigned short volatile async_len;/* length of data to sent */ - unsigned short volatile async_channel;/* channel number for async transfer */ - int volatile async_busy; /* flag != 0 sending in progress */ - int volatile net_tx_busy; /* a network packet tx is in progress */ - - /* network interface */ - void *netif; /* pointer to network structure */ - - /* init and deinit stopcard for booting, too */ - void (*stopcard) (struct HYSDN_CARD *); - void (*releasehardware) (struct HYSDN_CARD *); - - spinlock_t hysdn_lock; -#ifdef CONFIG_HYSDN_CAPI - struct hycapictrl_info { - char cardname[32]; - spinlock_t lock; - int versionlen; - char versionbuf[1024]; - char *version[HYSDN_MAXVERSION]; - - char infobuf[128]; /* for function procinfo */ - - struct HYSDN_CARD *card; - struct capi_ctr capi_ctrl; - struct sk_buff *skbs[HYSDN_MAX_CAPI_SKB]; - int in_idx, out_idx; /* indexes to buffer ring */ - int sk_count; /* number of buffers currently in ring */ - struct sk_buff *tx_skb; /* buffer for tx operation */ - - struct list_head ncci_head; - } *hyctrlinfo; -#endif /* CONFIG_HYSDN_CAPI */ -} hysdn_card; - -#ifdef CONFIG_HYSDN_CAPI -typedef struct hycapictrl_info hycapictrl_info; -#endif /* CONFIG_HYSDN_CAPI */ - - -/*****************/ -/* exported vars */ -/*****************/ -extern hysdn_card *card_root; /* pointer to first card */ - - - -/*************************/ -/* im/exported functions */ -/*************************/ - -/* hysdn_procconf.c */ -extern int hysdn_procconf_init(void); /* init proc config filesys */ -extern void hysdn_procconf_release(void); /* deinit proc config filesys */ - -/* hysdn_proclog.c */ -extern int hysdn_proclog_init(hysdn_card *); /* init proc log entry */ -extern void hysdn_proclog_release(hysdn_card *); /* deinit proc log entry */ -extern void hysdn_addlog(hysdn_card *, char *, ...); /* output data to log */ -extern void hysdn_card_errlog(hysdn_card *, tErrLogEntry *, int); /* output card log */ - -/* boardergo.c */ -extern int ergo_inithardware(hysdn_card *card); /* get hardware -> module init */ - -/* hysdn_boot.c */ -extern int pof_write_close(hysdn_card *); /* close proc file after writing pof */ -extern int pof_write_open(hysdn_card *, unsigned char **); /* open proc file for writing pof */ -extern int pof_write_buffer(hysdn_card *, int); /* write boot data to card */ -extern int EvalSysrTokData(hysdn_card *, unsigned char *, int); /* Check Sysready Token Data */ - -/* hysdn_sched.c */ -extern int hysdn_sched_tx(hysdn_card *, unsigned char *, - unsigned short volatile *, unsigned short volatile *, - unsigned short); -extern int hysdn_sched_rx(hysdn_card *, unsigned char *, unsigned short, - unsigned short); -extern int hysdn_tx_cfgline(hysdn_card *, unsigned char *, - unsigned short); /* send one cfg line */ - -/* hysdn_net.c */ -extern unsigned int hynet_enable; -extern int hysdn_net_create(hysdn_card *); /* create a new net device */ -extern int hysdn_net_release(hysdn_card *); /* delete the device */ -extern char *hysdn_net_getname(hysdn_card *); /* get name of net interface */ -extern void hysdn_tx_netack(hysdn_card *); /* acknowledge a packet tx */ -extern struct sk_buff *hysdn_tx_netget(hysdn_card *); /* get next network packet */ -extern void hysdn_rx_netpkt(hysdn_card *, unsigned char *, - unsigned short); /* rxed packet from network */ - -#ifdef CONFIG_HYSDN_CAPI -extern unsigned int hycapi_enable; -extern int hycapi_capi_create(hysdn_card *); /* create a new capi device */ -extern int hycapi_capi_release(hysdn_card *); /* delete the device */ -extern int hycapi_capi_stop(hysdn_card *card); /* suspend */ -extern void hycapi_rx_capipkt(hysdn_card *card, unsigned char *buf, - unsigned short len); -extern void hycapi_tx_capiack(hysdn_card *card); -extern struct sk_buff *hycapi_tx_capiget(hysdn_card *card); -extern int hycapi_init(void); -extern void hycapi_cleanup(void); -#endif /* CONFIG_HYSDN_CAPI */ - -#endif /* HYSDN_DEFS_H */ diff --git a/drivers/staging/isdn/hysdn/hysdn_init.c b/drivers/staging/isdn/hysdn/hysdn_init.c deleted file mode 100644 index 0db2f7506250..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_init.c +++ /dev/null @@ -1,213 +0,0 @@ -/* $Id: hysdn_init.c,v 1.6.6.6 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, init functions. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -static struct pci_device_id hysdn_pci_tbl[] = { - { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, - PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO, 0, 0, BD_METRO }, - { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, - PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2, 0, 0, BD_CHAMP2 }, - { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, - PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_ERGO, 0, 0, BD_ERGO }, - { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, - PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO, 0, 0, BD_ERGO }, - - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(pci, hysdn_pci_tbl); -MODULE_DESCRIPTION("ISDN4Linux: Driver for HYSDN cards"); -MODULE_AUTHOR("Werner Cornelius"); -MODULE_LICENSE("GPL"); - -static int cardmax; /* number of found cards */ -hysdn_card *card_root = NULL; /* pointer to first card */ -static hysdn_card *card_last = NULL; /* pointer to first card */ - - -/****************************************************************************/ -/* The module startup and shutdown code. Only compiled when used as module. */ -/* Using the driver as module is always advisable, because the booting */ -/* image becomes smaller and the driver code is only loaded when needed. */ -/* Additionally newer versions may be activated without rebooting. */ -/****************************************************************************/ - -/****************************************************************************/ -/* init_module is called once when the module is loaded to do all necessary */ -/* things like autodetect... */ -/* If the return value of this function is 0 the init has been successful */ -/* and the module is added to the list in /proc/modules, otherwise an error */ -/* is assumed and the module will not be kept in memory. */ -/****************************************************************************/ - -static int hysdn_pci_init_one(struct pci_dev *akt_pcidev, - const struct pci_device_id *ent) -{ - hysdn_card *card; - int rc; - - rc = pci_enable_device(akt_pcidev); - if (rc) - return rc; - - if (!(card = kzalloc(sizeof(hysdn_card), GFP_KERNEL))) { - printk(KERN_ERR "HYSDN: unable to alloc device mem \n"); - rc = -ENOMEM; - goto err_out; - } - card->myid = cardmax; /* set own id */ - card->bus = akt_pcidev->bus->number; - card->devfn = akt_pcidev->devfn; /* slot + function */ - card->subsysid = akt_pcidev->subsystem_device; - card->irq = akt_pcidev->irq; - card->iobase = pci_resource_start(akt_pcidev, PCI_REG_PLX_IO_BASE); - card->plxbase = pci_resource_start(akt_pcidev, PCI_REG_PLX_MEM_BASE); - card->membase = pci_resource_start(akt_pcidev, PCI_REG_MEMORY_BASE); - card->brdtype = BD_NONE; /* unknown */ - card->debug_flags = DEF_DEB_FLAGS; /* set default debug */ - card->faxchans = 0; /* default no fax channels */ - card->bchans = 2; /* and 2 b-channels */ - card->brdtype = ent->driver_data; - - if (ergo_inithardware(card)) { - printk(KERN_WARNING "HYSDN: card at io 0x%04x already in use\n", card->iobase); - rc = -EBUSY; - goto err_out_card; - } - - cardmax++; - card->next = NULL; /*end of chain */ - if (card_last) - card_last->next = card; /* pointer to next card */ - else - card_root = card; - card_last = card; /* new chain end */ - - pci_set_drvdata(akt_pcidev, card); - return 0; - -err_out_card: - kfree(card); -err_out: - pci_disable_device(akt_pcidev); - return rc; -} - -static void hysdn_pci_remove_one(struct pci_dev *akt_pcidev) -{ - hysdn_card *card = pci_get_drvdata(akt_pcidev); - - pci_set_drvdata(akt_pcidev, NULL); - - if (card->stopcard) - card->stopcard(card); - -#ifdef CONFIG_HYSDN_CAPI - hycapi_capi_release(card); -#endif - - if (card->releasehardware) - card->releasehardware(card); /* free all hardware resources */ - - if (card == card_root) { - card_root = card_root->next; - if (!card_root) - card_last = NULL; - } else { - hysdn_card *tmp = card_root; - while (tmp) { - if (tmp->next == card) - tmp->next = card->next; - card_last = tmp; - tmp = tmp->next; - } - } - - kfree(card); - pci_disable_device(akt_pcidev); -} - -static struct pci_driver hysdn_pci_driver = { - .name = "hysdn", - .id_table = hysdn_pci_tbl, - .probe = hysdn_pci_init_one, - .remove = hysdn_pci_remove_one, -}; - -static int hysdn_have_procfs; - -static int __init -hysdn_init(void) -{ - int rc; - - printk(KERN_NOTICE "HYSDN: module loaded\n"); - - rc = pci_register_driver(&hysdn_pci_driver); - if (rc) - return rc; - - printk(KERN_INFO "HYSDN: %d card(s) found.\n", cardmax); - - if (!hysdn_procconf_init()) - hysdn_have_procfs = 1; - -#ifdef CONFIG_HYSDN_CAPI - if (cardmax > 0) { - if (hycapi_init()) { - printk(KERN_ERR "HYCAPI: init failed\n"); - - if (hysdn_have_procfs) - hysdn_procconf_release(); - - pci_unregister_driver(&hysdn_pci_driver); - return -ESPIPE; - } - } -#endif /* CONFIG_HYSDN_CAPI */ - - return 0; /* no error */ -} /* init_module */ - - -/***********************************************************************/ -/* cleanup_module is called when the module is released by the kernel. */ -/* The routine is only called if init_module has been successful and */ -/* the module counter has a value of 0. Otherwise this function will */ -/* not be called. This function must release all resources still allo- */ -/* cated as after the return from this function the module code will */ -/* be removed from memory. */ -/***********************************************************************/ -static void __exit -hysdn_exit(void) -{ - if (hysdn_have_procfs) - hysdn_procconf_release(); - - pci_unregister_driver(&hysdn_pci_driver); - -#ifdef CONFIG_HYSDN_CAPI - hycapi_cleanup(); -#endif /* CONFIG_HYSDN_CAPI */ - - printk(KERN_NOTICE "HYSDN: module unloaded\n"); -} /* cleanup_module */ - -module_init(hysdn_init); -module_exit(hysdn_exit); diff --git a/drivers/staging/isdn/hysdn/hysdn_net.c b/drivers/staging/isdn/hysdn/hysdn_net.c deleted file mode 100644 index dcb9ef7a2651..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_net.c +++ /dev/null @@ -1,330 +0,0 @@ -/* $Id: hysdn_net.c,v 1.8.6.4 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, net (ethernet type) handling routines. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * This net module has been inspired by the skeleton driver from - * Donald Becker (becker@CESDIS.gsfc.nasa.gov) - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -unsigned int hynet_enable = 0xffffffff; -module_param(hynet_enable, uint, 0); - -#define MAX_SKB_BUFFERS 20 /* number of buffers for keeping TX-data */ - -/****************************************************************************/ -/* structure containing the complete network data. The structure is aligned */ -/* in a way that both, the device and statistics are kept inside it. */ -/* for proper access, the device structure MUST be the first var/struct */ -/* inside the definition. */ -/****************************************************************************/ -struct net_local { - /* Tx control lock. This protects the transmit buffer ring - * state along with the "tx full" state of the driver. This - * means all netif_queue flow control actions are protected - * by this lock as well. - */ - struct net_device *dev; - spinlock_t lock; - struct sk_buff *skbs[MAX_SKB_BUFFERS]; /* pointers to tx-skbs */ - int in_idx, out_idx; /* indexes to buffer ring */ - int sk_count; /* number of buffers currently in ring */ -}; /* net_local */ - - - -/*********************************************************************/ -/* Open/initialize the board. This is called (in the current kernel) */ -/* sometime after booting when the 'ifconfig' program is run. */ -/* This routine should set everything up anew at each open, even */ -/* registers that "should" only need to be set once at boot, so that */ -/* there is non-reboot way to recover if something goes wrong. */ -/*********************************************************************/ -static int -net_open(struct net_device *dev) -{ - struct in_device *in_dev; - hysdn_card *card = dev->ml_priv; - int i; - - netif_start_queue(dev); /* start tx-queueing */ - - /* Fill in the MAC-level header (if not already set) */ - if (!card->mac_addr[0]) { - for (i = 0; i < ETH_ALEN; i++) - dev->dev_addr[i] = 0xfc; - if ((in_dev = dev->ip_ptr) != NULL) { - const struct in_ifaddr *ifa; - - rcu_read_lock(); - ifa = rcu_dereference(in_dev->ifa_list); - if (ifa != NULL) - memcpy(dev->dev_addr + (ETH_ALEN - sizeof(ifa->ifa_local)), &ifa->ifa_local, sizeof(ifa->ifa_local)); - rcu_read_unlock(); - } - } else - memcpy(dev->dev_addr, card->mac_addr, ETH_ALEN); - - return (0); -} /* net_open */ - -/*******************************************/ -/* flush the currently occupied tx-buffers */ -/* must only be called when device closed */ -/*******************************************/ -static void -flush_tx_buffers(struct net_local *nl) -{ - - while (nl->sk_count) { - dev_kfree_skb(nl->skbs[nl->out_idx++]); /* free skb */ - if (nl->out_idx >= MAX_SKB_BUFFERS) - nl->out_idx = 0; /* wrap around */ - nl->sk_count--; - } -} /* flush_tx_buffers */ - - -/*********************************************************************/ -/* close/decativate the device. The device is not removed, but only */ -/* deactivated. */ -/*********************************************************************/ -static int -net_close(struct net_device *dev) -{ - - netif_stop_queue(dev); /* disable queueing */ - - flush_tx_buffers((struct net_local *) dev); - - return (0); /* success */ -} /* net_close */ - -/************************************/ -/* send a packet on this interface. */ -/* new style for kernel >= 2.3.33 */ -/************************************/ -static netdev_tx_t -net_send_packet(struct sk_buff *skb, struct net_device *dev) -{ - struct net_local *lp = (struct net_local *) dev; - - spin_lock_irq(&lp->lock); - - lp->skbs[lp->in_idx++] = skb; /* add to buffer list */ - if (lp->in_idx >= MAX_SKB_BUFFERS) - lp->in_idx = 0; /* wrap around */ - lp->sk_count++; /* adjust counter */ - netif_trans_update(dev); - - /* If we just used up the very last entry in the - * TX ring on this device, tell the queueing - * layer to send no more. - */ - if (lp->sk_count >= MAX_SKB_BUFFERS) - netif_stop_queue(dev); - - /* When the TX completion hw interrupt arrives, this - * is when the transmit statistics are updated. - */ - - spin_unlock_irq(&lp->lock); - - if (lp->sk_count <= 3) { - schedule_work(&((hysdn_card *) dev->ml_priv)->irq_queue); - } - return NETDEV_TX_OK; /* success */ -} /* net_send_packet */ - - - -/***********************************************************************/ -/* acknowlegde a packet send. The network layer will be informed about */ -/* completion */ -/***********************************************************************/ -void -hysdn_tx_netack(hysdn_card *card) -{ - struct net_local *lp = card->netif; - - if (!lp) - return; /* non existing device */ - - - if (!lp->sk_count) - return; /* error condition */ - - lp->dev->stats.tx_packets++; - lp->dev->stats.tx_bytes += lp->skbs[lp->out_idx]->len; - - dev_kfree_skb(lp->skbs[lp->out_idx++]); /* free skb */ - if (lp->out_idx >= MAX_SKB_BUFFERS) - lp->out_idx = 0; /* wrap around */ - - if (lp->sk_count-- == MAX_SKB_BUFFERS) /* dec usage count */ - netif_start_queue((struct net_device *) lp); -} /* hysdn_tx_netack */ - -/*****************************************************/ -/* we got a packet from the network, go and queue it */ -/*****************************************************/ -void -hysdn_rx_netpkt(hysdn_card *card, unsigned char *buf, unsigned short len) -{ - struct net_local *lp = card->netif; - struct net_device *dev; - struct sk_buff *skb; - - if (!lp) - return; /* non existing device */ - - dev = lp->dev; - dev->stats.rx_bytes += len; - - skb = dev_alloc_skb(len); - if (skb == NULL) { - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - return; - } - /* copy the data */ - skb_put_data(skb, buf, len); - - /* determine the used protocol */ - skb->protocol = eth_type_trans(skb, dev); - - dev->stats.rx_packets++; /* adjust packet count */ - - netif_rx(skb); -} /* hysdn_rx_netpkt */ - -/*****************************************************/ -/* return the pointer to a network packet to be send */ -/*****************************************************/ -struct sk_buff * -hysdn_tx_netget(hysdn_card *card) -{ - struct net_local *lp = card->netif; - - if (!lp) - return (NULL); /* non existing device */ - - if (!lp->sk_count) - return (NULL); /* nothing available */ - - return (lp->skbs[lp->out_idx]); /* next packet to send */ -} /* hysdn_tx_netget */ - -static const struct net_device_ops hysdn_netdev_ops = { - .ndo_open = net_open, - .ndo_stop = net_close, - .ndo_start_xmit = net_send_packet, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - - -/*****************************************************************************/ -/* hysdn_net_create creates a new net device for the given card. If a device */ -/* already exists, it will be deleted and created a new one. The return value */ -/* 0 announces success, else a negative error code will be returned. */ -/*****************************************************************************/ -int -hysdn_net_create(hysdn_card *card) -{ - struct net_device *dev; - int i; - struct net_local *lp; - - if (!card) { - printk(KERN_WARNING "No card-pt in hysdn_net_create!\n"); - return (-ENOMEM); - } - hysdn_net_release(card); /* release an existing net device */ - - dev = alloc_etherdev(sizeof(struct net_local)); - if (!dev) { - printk(KERN_WARNING "HYSDN: unable to allocate mem\n"); - return (-ENOMEM); - } - - lp = netdev_priv(dev); - lp->dev = dev; - - dev->netdev_ops = &hysdn_netdev_ops; - spin_lock_init(&((struct net_local *) dev)->lock); - - /* initialise necessary or informing fields */ - dev->base_addr = card->iobase; /* IO address */ - dev->irq = card->irq; /* irq */ - - dev->netdev_ops = &hysdn_netdev_ops; - if ((i = register_netdev(dev))) { - printk(KERN_WARNING "HYSDN: unable to create network device\n"); - free_netdev(dev); - return (i); - } - dev->ml_priv = card; /* remember pointer to own data structure */ - card->netif = dev; /* setup the local pointer */ - - if (card->debug_flags & LOG_NET_INIT) - hysdn_addlog(card, "network device created"); - return 0; /* and return success */ -} /* hysdn_net_create */ - -/***************************************************************************/ -/* hysdn_net_release deletes the net device for the given card. The return */ -/* value 0 announces success, else a negative error code will be returned. */ -/***************************************************************************/ -int -hysdn_net_release(hysdn_card *card) -{ - struct net_device *dev = card->netif; - - if (!dev) - return (0); /* non existing */ - - card->netif = NULL; /* clear out pointer */ - net_close(dev); - - flush_tx_buffers((struct net_local *) dev); /* empty buffers */ - - unregister_netdev(dev); /* release the device */ - free_netdev(dev); /* release the memory allocated */ - if (card->debug_flags & LOG_NET_INIT) - hysdn_addlog(card, "network device deleted"); - - return (0); /* always successful */ -} /* hysdn_net_release */ - -/*****************************************************************************/ -/* hysdn_net_getname returns a pointer to the name of the network interface. */ -/* if the interface is not existing, a "-" is returned. */ -/*****************************************************************************/ -char * -hysdn_net_getname(hysdn_card *card) -{ - struct net_device *dev = card->netif; - - if (!dev) - return ("-"); /* non existing */ - - return (dev->name); -} /* hysdn_net_getname */ diff --git a/drivers/staging/isdn/hysdn/hysdn_pof.h b/drivers/staging/isdn/hysdn/hysdn_pof.h deleted file mode 100644 index f63f5fa59d7e..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_pof.h +++ /dev/null @@ -1,78 +0,0 @@ -/* $Id: hysdn_pof.h,v 1.2.6.1 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, definitions used for handling pof-files. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -/************************/ -/* POF specific defines */ -/************************/ -#define BOOT_BUF_SIZE 0x1000 /* =4096, maybe moved to other h file */ -#define CRYPT_FEEDTERM 0x8142 -#define CRYPT_STARTTERM 0x81a5 -/* max. timeout time in seconds - * from end of booting to POF is ready - */ -#define POF_READY_TIME_OUT_SEC 10 - -/**********************************/ -/* defines for 1.stage boot image */ -/**********************************/ - -/* the POF file record containing the boot loader image - * has 2 pages a 16KB: - * 1. page contains the high 16-bit part of the 32-bit E1 words - * 2. page contains the low 16-bit part of the 32-bit E1 words - * - * In each 16KB page we assume the start of the boot loader code - * in the highest 2KB part (at offset 0x3800); - * the rest (0x0000..0x37FF) is assumed to contain 0 bytes. - */ - -#define POF_BOOT_LOADER_PAGE_SIZE 0x4000 /* =16384U */ -#define POF_BOOT_LOADER_TOTAL_SIZE (2U * POF_BOOT_LOADER_PAGE_SIZE) - -#define POF_BOOT_LOADER_CODE_SIZE 0x0800 /* =2KB =2048U */ - -/* offset in boot page, where loader code may start */ -/* =0x3800= 14336U */ -#define POF_BOOT_LOADER_OFF_IN_PAGE (POF_BOOT_LOADER_PAGE_SIZE-POF_BOOT_LOADER_CODE_SIZE) - - -/*--------------------------------------POF file record structs------------*/ -typedef struct PofFileHdr_tag { /* Pof file header */ - /*00 */ unsigned long Magic __attribute__((packed)); - /*04 */ unsigned long N_PofRecs __attribute__((packed)); -/*08 */ -} tPofFileHdr; - -typedef struct PofRecHdr_tag { /* Pof record header */ - /*00 */ unsigned short PofRecId __attribute__((packed)); - /*02 */ unsigned long PofRecDataLen __attribute__((packed)); -/*06 */ -} tPofRecHdr; - -typedef struct PofTimeStamp_tag { - /*00 */ unsigned long UnixTime __attribute__((packed)); - /*04 */ unsigned char DateTimeText[0x28]; - /* =40 */ -/*2C */ -} tPofTimeStamp; - -/* tPofFileHdr.Magic value: */ -#define TAGFILEMAGIC 0x464F501AUL -/* tPofRecHdr.PofRecId values: */ -#define TAG_ABSDATA 0x1000 /* abs. data */ -#define TAG_BOOTDTA 0x1001 /* boot data */ -#define TAG_COMMENT 0x0020 -#define TAG_SYSCALL 0x0021 -#define TAG_FLOWCTRL 0x0022 -#define TAG_TIMESTMP 0x0010 /* date/time stamp of version */ -#define TAG_CABSDATA 0x1100 /* crypted abs. data */ -#define TAG_CBOOTDTA 0x1101 /* crypted boot data */ diff --git a/drivers/staging/isdn/hysdn/hysdn_procconf.c b/drivers/staging/isdn/hysdn/hysdn_procconf.c deleted file mode 100644 index 48afd9f5316e..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_procconf.c +++ /dev/null @@ -1,411 +0,0 @@ -/* $Id: hysdn_procconf.c,v 1.8.6.4 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, /proc/net filesystem dir and conf functions. - * - * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH - * - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -static DEFINE_MUTEX(hysdn_conf_mutex); - -#define INFO_OUT_LEN 80 /* length of info line including lf */ - -/********************************************************/ -/* defines and data structure for conf write operations */ -/********************************************************/ -#define CONF_STATE_DETECT 0 /* waiting for detect */ -#define CONF_STATE_CONF 1 /* writing config data */ -#define CONF_STATE_POF 2 /* writing pof data */ -#define CONF_LINE_LEN 255 /* 255 chars max */ - -struct conf_writedata { - hysdn_card *card; /* card the device is connected to */ - int buf_size; /* actual number of bytes in the buffer */ - int needed_size; /* needed size when reading pof */ - int state; /* actual interface states from above constants */ - unsigned char conf_line[CONF_LINE_LEN]; /* buffered conf line */ - unsigned short channel; /* active channel number */ - unsigned char *pof_buffer; /* buffer when writing pof */ -}; - -/***********************************************************************/ -/* process_line parses one config line and transfers it to the card if */ -/* necessary. */ -/* if the return value is negative an error occurred. */ -/***********************************************************************/ -static int -process_line(struct conf_writedata *cnf) -{ - unsigned char *cp = cnf->conf_line; - int i; - - if (cnf->card->debug_flags & LOG_CNF_LINE) - hysdn_addlog(cnf->card, "conf line: %s", cp); - - if (*cp == '-') { /* option */ - cp++; /* point to option char */ - - if (*cp++ != 'c') - return (0); /* option unknown or used */ - i = 0; /* start value for channel */ - while ((*cp <= '9') && (*cp >= '0')) - i = i * 10 + *cp++ - '0'; /* get decimal number */ - if (i > 65535) { - if (cnf->card->debug_flags & LOG_CNF_MISC) - hysdn_addlog(cnf->card, "conf channel invalid %d", i); - return (-ERR_INV_CHAN); /* invalid channel */ - } - cnf->channel = i & 0xFFFF; /* set new channel number */ - return (0); /* success */ - } /* option */ - if (*cp == '*') { /* line to send */ - if (cnf->card->debug_flags & LOG_CNF_DATA) - hysdn_addlog(cnf->card, "conf chan=%d %s", cnf->channel, cp); - return (hysdn_tx_cfgline(cnf->card, cnf->conf_line + 1, - cnf->channel)); /* send the line without * */ - } /* line to send */ - return (0); -} /* process_line */ - -/***********************************/ -/* conf file operations and tables */ -/***********************************/ - -/****************************************************/ -/* write conf file -> boot or send cfg line to card */ -/****************************************************/ -static ssize_t -hysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t *off) -{ - struct conf_writedata *cnf; - int i; - unsigned char ch, *cp; - - if (!count) - return (0); /* nothing to handle */ - - if (!(cnf = file->private_data)) - return (-EFAULT); /* should never happen */ - - if (cnf->state == CONF_STATE_DETECT) { /* auto detect cnf or pof data */ - if (copy_from_user(&ch, buf, 1)) /* get first char for detect */ - return (-EFAULT); - - if (ch == 0x1A) { - /* we detected a pof file */ - if ((cnf->needed_size = pof_write_open(cnf->card, &cnf->pof_buffer)) <= 0) - return (cnf->needed_size); /* an error occurred -> exit */ - cnf->buf_size = 0; /* buffer is empty */ - cnf->state = CONF_STATE_POF; /* new state */ - } else { - /* conf data has been detected */ - cnf->buf_size = 0; /* buffer is empty */ - cnf->state = CONF_STATE_CONF; /* requested conf data write */ - if (cnf->card->state != CARD_STATE_RUN) - return (-ERR_NOT_BOOTED); - cnf->conf_line[CONF_LINE_LEN - 1] = 0; /* limit string length */ - cnf->channel = 4098; /* default channel for output */ - } - } /* state was auto detect */ - if (cnf->state == CONF_STATE_POF) { /* pof write active */ - i = cnf->needed_size - cnf->buf_size; /* bytes still missing for write */ - if (i <= 0) - return (-EINVAL); /* size error handling pof */ - - if (i < count) - count = i; /* limit requested number of bytes */ - if (copy_from_user(cnf->pof_buffer + cnf->buf_size, buf, count)) - return (-EFAULT); /* error while copying */ - cnf->buf_size += count; - - if (cnf->needed_size == cnf->buf_size) { - cnf->needed_size = pof_write_buffer(cnf->card, cnf->buf_size); /* write data */ - if (cnf->needed_size <= 0) { - cnf->card->state = CARD_STATE_BOOTERR; /* show boot error */ - return (cnf->needed_size); /* an error occurred */ - } - cnf->buf_size = 0; /* buffer is empty again */ - } - } - /* pof write active */ - else { /* conf write active */ - - if (cnf->card->state != CARD_STATE_RUN) { - if (cnf->card->debug_flags & LOG_CNF_MISC) - hysdn_addlog(cnf->card, "cnf write denied -> not booted"); - return (-ERR_NOT_BOOTED); - } - i = (CONF_LINE_LEN - 1) - cnf->buf_size; /* bytes available in buffer */ - if (i > 0) { - /* copy remaining bytes into buffer */ - - if (count > i) - count = i; /* limit transfer */ - if (copy_from_user(cnf->conf_line + cnf->buf_size, buf, count)) - return (-EFAULT); /* error while copying */ - - i = count; /* number of chars in buffer */ - cp = cnf->conf_line + cnf->buf_size; - while (i) { - /* search for end of line */ - if ((*cp < ' ') && (*cp != 9)) - break; /* end of line found */ - cp++; - i--; - } /* search for end of line */ - - if (i) { - /* delimiter found */ - *cp++ = 0; /* string termination */ - count -= (i - 1); /* subtract remaining bytes from count */ - while ((i) && (*cp < ' ') && (*cp != 9)) { - i--; /* discard next char */ - count++; /* mark as read */ - cp++; /* next char */ - } - cnf->buf_size = 0; /* buffer is empty after transfer */ - if ((i = process_line(cnf)) < 0) /* handle the line */ - count = i; /* return the error */ - } - /* delimiter found */ - else { - cnf->buf_size += count; /* add chars to string */ - if (cnf->buf_size >= CONF_LINE_LEN - 1) { - if (cnf->card->debug_flags & LOG_CNF_MISC) - hysdn_addlog(cnf->card, "cnf line too long %d chars pos %d", cnf->buf_size, count); - return (-ERR_CONF_LONG); - } - } /* not delimited */ - - } - /* copy remaining bytes into buffer */ - else { - if (cnf->card->debug_flags & LOG_CNF_MISC) - hysdn_addlog(cnf->card, "cnf line too long"); - return (-ERR_CONF_LONG); - } - } /* conf write active */ - - return (count); -} /* hysdn_conf_write */ - -/*******************************************/ -/* read conf file -> output card info data */ -/*******************************************/ -static ssize_t -hysdn_conf_read(struct file *file, char __user *buf, size_t count, loff_t *off) -{ - char *cp; - - if (!(file->f_mode & FMODE_READ)) - return -EPERM; /* no permission to read */ - - if (!(cp = file->private_data)) - return -EFAULT; /* should never happen */ - - return simple_read_from_buffer(buf, count, off, cp, strlen(cp)); -} /* hysdn_conf_read */ - -/******************/ -/* open conf file */ -/******************/ -static int -hysdn_conf_open(struct inode *ino, struct file *filep) -{ - hysdn_card *card; - struct conf_writedata *cnf; - char *cp, *tmp; - - /* now search the addressed card */ - mutex_lock(&hysdn_conf_mutex); - card = PDE_DATA(ino); - if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL)) - hysdn_addlog(card, "config open for uid=%d gid=%d mode=0x%x", - filep->f_cred->fsuid, filep->f_cred->fsgid, - filep->f_mode); - - if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { - /* write only access -> write boot file or conf line */ - - if (!(cnf = kmalloc(sizeof(struct conf_writedata), GFP_KERNEL))) { - mutex_unlock(&hysdn_conf_mutex); - return (-EFAULT); - } - cnf->card = card; - cnf->buf_size = 0; /* nothing buffered */ - cnf->state = CONF_STATE_DETECT; /* start auto detect */ - filep->private_data = cnf; - - } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { - /* read access -> output card info data */ - - if (!(tmp = kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) { - mutex_unlock(&hysdn_conf_mutex); - return (-EFAULT); /* out of memory */ - } - filep->private_data = tmp; /* start of string */ - - /* first output a headline */ - sprintf(tmp, "id bus slot type irq iobase dp-mem b-chans fax-chans state device"); - cp = tmp; /* start of string */ - while (*cp) - cp++; - while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN) - *cp++ = ' '; - *cp++ = '\n'; - - /* and now the data */ - sprintf(cp, "%d %3d %4d %4d %3d 0x%04x 0x%08lx %7d %9d %3d %s", - card->myid, - card->bus, - PCI_SLOT(card->devfn), - card->brdtype, - card->irq, - card->iobase, - card->membase, - card->bchans, - card->faxchans, - card->state, - hysdn_net_getname(card)); - while (*cp) - cp++; - while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN) - *cp++ = ' '; - *cp++ = '\n'; - *cp = 0; /* end of string */ - } else { /* simultaneous read/write access forbidden ! */ - mutex_unlock(&hysdn_conf_mutex); - return (-EPERM); /* no permission this time */ - } - mutex_unlock(&hysdn_conf_mutex); - return nonseekable_open(ino, filep); -} /* hysdn_conf_open */ - -/***************************/ -/* close a config file. */ -/***************************/ -static int -hysdn_conf_close(struct inode *ino, struct file *filep) -{ - hysdn_card *card; - struct conf_writedata *cnf; - int retval = 0; - - mutex_lock(&hysdn_conf_mutex); - card = PDE_DATA(ino); - if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL)) - hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x", - filep->f_cred->fsuid, filep->f_cred->fsgid, - filep->f_mode); - - if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { - /* write only access -> write boot file or conf line */ - if (filep->private_data) { - cnf = filep->private_data; - - if (cnf->state == CONF_STATE_POF) - retval = pof_write_close(cnf->card); /* close the pof write */ - kfree(filep->private_data); /* free allocated memory for buffer */ - - } /* handle write private data */ - } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { - /* read access -> output card info data */ - - kfree(filep->private_data); /* release memory */ - } - mutex_unlock(&hysdn_conf_mutex); - return (retval); -} /* hysdn_conf_close */ - -/******************************************************/ -/* table for conf filesystem functions defined above. */ -/******************************************************/ -static const struct file_operations conf_fops = -{ - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = hysdn_conf_read, - .write = hysdn_conf_write, - .open = hysdn_conf_open, - .release = hysdn_conf_close, -}; - -/*****************************/ -/* hysdn subdir in /proc/net */ -/*****************************/ -struct proc_dir_entry *hysdn_proc_entry = NULL; - -/*******************************************************************************/ -/* hysdn_procconf_init is called when the module is loaded and after the cards */ -/* have been detected. The needed proc dir and card config files are created. */ -/* The log init is called at last. */ -/*******************************************************************************/ -int -hysdn_procconf_init(void) -{ - hysdn_card *card; - unsigned char conf_name[20]; - - hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, init_net.proc_net); - if (!hysdn_proc_entry) { - printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n"); - return (-1); - } - card = card_root; /* point to first card */ - while (card) { - - sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid); - if ((card->procconf = (void *) proc_create_data(conf_name, - S_IFREG | S_IRUGO | S_IWUSR, - hysdn_proc_entry, - &conf_fops, - card)) != NULL) { - hysdn_proclog_init(card); /* init the log file entry */ - } - card = card->next; /* next entry */ - } - - printk(KERN_NOTICE "HYSDN: procfs initialised\n"); - return 0; -} /* hysdn_procconf_init */ - -/*************************************************************************************/ -/* hysdn_procconf_release is called when the module is unloaded and before the cards */ -/* resources are released. The module counter is assumed to be 0 ! */ -/*************************************************************************************/ -void -hysdn_procconf_release(void) -{ - hysdn_card *card; - unsigned char conf_name[20]; - - card = card_root; /* start with first card */ - while (card) { - - sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid); - if (card->procconf) - remove_proc_entry(conf_name, hysdn_proc_entry); - - hysdn_proclog_release(card); /* init the log file entry */ - - card = card->next; /* point to next card */ - } - - remove_proc_entry(PROC_SUBDIR_NAME, init_net.proc_net); -} diff --git a/drivers/staging/isdn/hysdn/hysdn_proclog.c b/drivers/staging/isdn/hysdn/hysdn_proclog.c deleted file mode 100644 index 6e898b90e86e..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_proclog.c +++ /dev/null @@ -1,357 +0,0 @@ -/* $Id: hysdn_proclog.c,v 1.9.6.3 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, /proc/net filesystem log functions. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -/* the proc subdir for the interface is defined in the procconf module */ -extern struct proc_dir_entry *hysdn_proc_entry; - -static DEFINE_MUTEX(hysdn_log_mutex); -static void put_log_buffer(hysdn_card *card, char *cp); - -/*************************************************/ -/* structure keeping ascii log for device output */ -/*************************************************/ -struct log_data { - struct log_data *next; - unsigned long usage_cnt;/* number of files still to work */ - void *proc_ctrl; /* pointer to own control procdata structure */ - char log_start[2]; /* log string start (final len aligned by size) */ -}; - -/**********************************************/ -/* structure holding proc entrys for one card */ -/**********************************************/ -struct procdata { - struct proc_dir_entry *log; /* log entry */ - char log_name[15]; /* log filename */ - struct log_data *log_head, *log_tail; /* head and tail for queue */ - int if_used; /* open count for interface */ - unsigned char logtmp[LOG_MAX_LINELEN]; - wait_queue_head_t rd_queue; -}; - - -/**********************************************/ -/* log function for cards error log interface */ -/**********************************************/ -void -hysdn_card_errlog(hysdn_card *card, tErrLogEntry *logp, int maxsize) -{ - char buf[ERRLOG_TEXT_SIZE + 40]; - - sprintf(buf, "LOG 0x%08lX 0x%08lX : %s\n", logp->ulErrType, logp->ulErrSubtype, logp->ucText); - put_log_buffer(card, buf); /* output the string */ -} /* hysdn_card_errlog */ - -/***************************************************/ -/* Log function using format specifiers for output */ -/***************************************************/ -void -hysdn_addlog(hysdn_card *card, char *fmt, ...) -{ - struct procdata *pd = card->proclog; - char *cp; - va_list args; - - if (!pd) - return; /* log structure non existent */ - - cp = pd->logtmp; - cp += sprintf(cp, "HYSDN: card %d ", card->myid); - - va_start(args, fmt); - cp += vsprintf(cp, fmt, args); - va_end(args); - *cp++ = '\n'; - *cp = 0; - - if (card->debug_flags & DEB_OUT_SYSLOG) - printk(KERN_INFO "%s", pd->logtmp); - else - put_log_buffer(card, pd->logtmp); - -} /* hysdn_addlog */ - -/********************************************/ -/* put an log buffer into the log queue. */ -/* This buffer will be kept until all files */ -/* opened for read got the contents. */ -/* Flushes buffers not longer in use. */ -/********************************************/ -static void -put_log_buffer(hysdn_card *card, char *cp) -{ - struct log_data *ib; - struct procdata *pd = card->proclog; - unsigned long flags; - - if (!pd) - return; - if (!cp) - return; - if (!*cp) - return; - if (pd->if_used <= 0) - return; /* no open file for read */ - - if (!(ib = kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC))) - return; /* no memory */ - strcpy(ib->log_start, cp); /* set output string */ - ib->next = NULL; - ib->proc_ctrl = pd; /* point to own control structure */ - spin_lock_irqsave(&card->hysdn_lock, flags); - ib->usage_cnt = pd->if_used; - if (!pd->log_head) - pd->log_head = ib; /* new head */ - else - pd->log_tail->next = ib; /* follows existing messages */ - pd->log_tail = ib; /* new tail */ - - /* delete old entrys */ - while (pd->log_head->next) { - if ((pd->log_head->usage_cnt <= 0) && - (pd->log_head->next->usage_cnt <= 0)) { - ib = pd->log_head; - pd->log_head = pd->log_head->next; - kfree(ib); - } else { - break; - } - } /* pd->log_head->next */ - - spin_unlock_irqrestore(&card->hysdn_lock, flags); - - wake_up_interruptible(&(pd->rd_queue)); /* announce new entry */ -} /* put_log_buffer */ - - -/******************************/ -/* file operations and tables */ -/******************************/ - -/****************************************/ -/* write log file -> set log level bits */ -/****************************************/ -static ssize_t -hysdn_log_write(struct file *file, const char __user *buf, size_t count, loff_t *off) -{ - int rc; - hysdn_card *card = file->private_data; - - rc = kstrtoul_from_user(buf, count, 0, &card->debug_flags); - if (rc < 0) - return rc; - hysdn_addlog(card, "debug set to 0x%lx", card->debug_flags); - return (count); -} /* hysdn_log_write */ - -/******************/ -/* read log file */ -/******************/ -static ssize_t -hysdn_log_read(struct file *file, char __user *buf, size_t count, loff_t *off) -{ - struct log_data *inf; - int len; - hysdn_card *card = PDE_DATA(file_inode(file)); - - if (!(inf = *((struct log_data **) file->private_data))) { - struct procdata *pd = card->proclog; - if (file->f_flags & O_NONBLOCK) - return (-EAGAIN); - - wait_event_interruptible(pd->rd_queue, (inf = - *((struct log_data **) file->private_data))); - } - if (!inf) - return (0); - - inf->usage_cnt--; /* new usage count */ - file->private_data = &inf->next; /* next structure */ - if ((len = strlen(inf->log_start)) <= count) { - if (copy_to_user(buf, inf->log_start, len)) - return -EFAULT; - *off += len; - return (len); - } - return (0); -} /* hysdn_log_read */ - -/******************/ -/* open log file */ -/******************/ -static int -hysdn_log_open(struct inode *ino, struct file *filep) -{ - hysdn_card *card = PDE_DATA(ino); - - mutex_lock(&hysdn_log_mutex); - if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { - /* write only access -> write log level only */ - filep->private_data = card; /* remember our own card */ - } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { - struct procdata *pd = card->proclog; - unsigned long flags; - - /* read access -> log/debug read */ - spin_lock_irqsave(&card->hysdn_lock, flags); - pd->if_used++; - if (pd->log_head) - filep->private_data = &pd->log_tail->next; - else - filep->private_data = &pd->log_head; - spin_unlock_irqrestore(&card->hysdn_lock, flags); - } else { /* simultaneous read/write access forbidden ! */ - mutex_unlock(&hysdn_log_mutex); - return (-EPERM); /* no permission this time */ - } - mutex_unlock(&hysdn_log_mutex); - return nonseekable_open(ino, filep); -} /* hysdn_log_open */ - -/*******************************************************************************/ -/* close a cardlog file. If the file has been opened for exclusive write it is */ -/* assumed as pof data input and the pof loader is noticed about. */ -/* Otherwise file is handled as log output. In this case the interface usage */ -/* count is decremented and all buffers are noticed of closing. If this file */ -/* was the last one to be closed, all buffers are freed. */ -/*******************************************************************************/ -static int -hysdn_log_close(struct inode *ino, struct file *filep) -{ - struct log_data *inf; - struct procdata *pd; - hysdn_card *card; - int retval = 0; - - mutex_lock(&hysdn_log_mutex); - if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { - /* write only access -> write debug level written */ - retval = 0; /* success */ - } else { - /* read access -> log/debug read, mark one further file as closed */ - - inf = *((struct log_data **) filep->private_data); /* get first log entry */ - if (inf) - pd = (struct procdata *) inf->proc_ctrl; /* still entries there */ - else { - /* no info available -> search card */ - card = PDE_DATA(file_inode(filep)); - pd = card->proclog; /* pointer to procfs log */ - } - if (pd) - pd->if_used--; /* decrement interface usage count by one */ - - while (inf) { - inf->usage_cnt--; /* decrement usage count for buffers */ - inf = inf->next; - } - - if (pd) - if (pd->if_used <= 0) /* delete buffers if last file closed */ - while (pd->log_head) { - inf = pd->log_head; - pd->log_head = pd->log_head->next; - kfree(inf); - } - } /* read access */ - mutex_unlock(&hysdn_log_mutex); - - return (retval); -} /* hysdn_log_close */ - -/*************************************************/ -/* select/poll routine to be able using select() */ -/*************************************************/ -static __poll_t -hysdn_log_poll(struct file *file, poll_table *wait) -{ - __poll_t mask = 0; - hysdn_card *card = PDE_DATA(file_inode(file)); - struct procdata *pd = card->proclog; - - if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) - return (mask); /* no polling for write supported */ - - poll_wait(file, &(pd->rd_queue), wait); - - if (*((struct log_data **) file->private_data)) - mask |= EPOLLIN | EPOLLRDNORM; - - return mask; -} /* hysdn_log_poll */ - -/**************************************************/ -/* table for log filesystem functions defined above. */ -/**************************************************/ -static const struct file_operations log_fops = -{ - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = hysdn_log_read, - .write = hysdn_log_write, - .poll = hysdn_log_poll, - .open = hysdn_log_open, - .release = hysdn_log_close, -}; - - -/***********************************************************************************/ -/* hysdn_proclog_init is called when the module is loaded after creating the cards */ -/* conf files. */ -/***********************************************************************************/ -int -hysdn_proclog_init(hysdn_card *card) -{ - struct procdata *pd; - - /* create a cardlog proc entry */ - - if ((pd = kzalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) { - sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid); - pd->log = proc_create_data(pd->log_name, - S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry, - &log_fops, card); - - init_waitqueue_head(&(pd->rd_queue)); - - card->proclog = (void *) pd; /* remember procfs structure */ - } - return (0); -} /* hysdn_proclog_init */ - -/************************************************************************************/ -/* hysdn_proclog_release is called when the module is unloaded and before the cards */ -/* conf file is released */ -/* The module counter is assumed to be 0 ! */ -/************************************************************************************/ -void -hysdn_proclog_release(hysdn_card *card) -{ - struct procdata *pd; - - if ((pd = (struct procdata *) card->proclog) != NULL) { - if (pd->log) - remove_proc_entry(pd->log_name, hysdn_proc_entry); - kfree(pd); /* release memory */ - card->proclog = NULL; - } -} /* hysdn_proclog_release */ diff --git a/drivers/staging/isdn/hysdn/hysdn_sched.c b/drivers/staging/isdn/hysdn/hysdn_sched.c deleted file mode 100644 index 31d7c1415543..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_sched.c +++ /dev/null @@ -1,197 +0,0 @@ -/* $Id: hysdn_sched.c,v 1.5.6.4 2001/11/06 21:58:19 kai Exp $ - * - * Linux driver for HYSDN cards - * scheduler routines for handling exchange card <-> pc. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -/*****************************************************************************/ -/* hysdn_sched_rx is called from the cards handler to announce new data is */ -/* available from the card. The routine has to handle the data and return */ -/* with a nonzero code if the data could be worked (or even thrown away), if */ -/* no room to buffer the data is available a zero return tells the card */ -/* to keep the data until later. */ -/*****************************************************************************/ -int -hysdn_sched_rx(hysdn_card *card, unsigned char *buf, unsigned short len, - unsigned short chan) -{ - - switch (chan) { - case CHAN_NDIS_DATA: - if (hynet_enable & (1 << card->myid)) { - /* give packet to network handler */ - hysdn_rx_netpkt(card, buf, len); - } - break; - - case CHAN_ERRLOG: - hysdn_card_errlog(card, (tErrLogEntry *) buf, len); - if (card->err_log_state == ERRLOG_STATE_ON) - card->err_log_state = ERRLOG_STATE_START; /* start new fetch */ - break; -#ifdef CONFIG_HYSDN_CAPI - case CHAN_CAPI: -/* give packet to CAPI handler */ - if (hycapi_enable & (1 << card->myid)) { - hycapi_rx_capipkt(card, buf, len); - } - break; -#endif /* CONFIG_HYSDN_CAPI */ - default: - printk(KERN_INFO "irq message channel %d len %d unhandled \n", chan, len); - break; - - } /* switch rx channel */ - - return (1); /* always handled */ -} /* hysdn_sched_rx */ - -/*****************************************************************************/ -/* hysdn_sched_tx is called from the cards handler to announce that there is */ -/* room in the tx-buffer to the card and data may be sent if needed. */ -/* If the routine wants to send data it must fill buf, len and chan with the */ -/* appropriate data and return a nonzero value. With a zero return no new */ -/* data to send is assumed. maxlen specifies the buffer size available for */ -/* sending. */ -/*****************************************************************************/ -int -hysdn_sched_tx(hysdn_card *card, unsigned char *buf, - unsigned short volatile *len, unsigned short volatile *chan, - unsigned short maxlen) -{ - struct sk_buff *skb; - - if (card->net_tx_busy) { - card->net_tx_busy = 0; /* reset flag */ - hysdn_tx_netack(card); /* acknowledge packet send */ - } /* a network packet has completely been transferred */ - /* first of all async requests are handled */ - if (card->async_busy) { - if (card->async_len <= maxlen) { - memcpy(buf, card->async_data, card->async_len); - *len = card->async_len; - *chan = card->async_channel; - card->async_busy = 0; /* reset request */ - return (1); - } - card->async_busy = 0; /* in case of length error */ - } /* async request */ - if ((card->err_log_state == ERRLOG_STATE_START) && - (maxlen >= ERRLOG_CMD_REQ_SIZE)) { - strcpy(buf, ERRLOG_CMD_REQ); /* copy the command */ - *len = ERRLOG_CMD_REQ_SIZE; /* buffer length */ - *chan = CHAN_ERRLOG; /* and channel */ - card->err_log_state = ERRLOG_STATE_ON; /* new state is on */ - return (1); /* tell that data should be send */ - } /* error log start and able to send */ - if ((card->err_log_state == ERRLOG_STATE_STOP) && - (maxlen >= ERRLOG_CMD_STOP_SIZE)) { - strcpy(buf, ERRLOG_CMD_STOP); /* copy the command */ - *len = ERRLOG_CMD_STOP_SIZE; /* buffer length */ - *chan = CHAN_ERRLOG; /* and channel */ - card->err_log_state = ERRLOG_STATE_OFF; /* new state is off */ - return (1); /* tell that data should be send */ - } /* error log start and able to send */ - /* now handle network interface packets */ - if ((hynet_enable & (1 << card->myid)) && - (skb = hysdn_tx_netget(card)) != NULL) - { - if (skb->len <= maxlen) { - /* copy the packet to the buffer */ - skb_copy_from_linear_data(skb, buf, skb->len); - *len = skb->len; - *chan = CHAN_NDIS_DATA; - card->net_tx_busy = 1; /* we are busy sending network data */ - return (1); /* go and send the data */ - } else - hysdn_tx_netack(card); /* aknowledge packet -> throw away */ - } /* send a network packet if available */ -#ifdef CONFIG_HYSDN_CAPI - if (((hycapi_enable & (1 << card->myid))) && - ((skb = hycapi_tx_capiget(card)) != NULL)) - { - if (skb->len <= maxlen) { - skb_copy_from_linear_data(skb, buf, skb->len); - *len = skb->len; - *chan = CHAN_CAPI; - hycapi_tx_capiack(card); - return (1); /* go and send the data */ - } - } -#endif /* CONFIG_HYSDN_CAPI */ - return (0); /* nothing to send */ -} /* hysdn_sched_tx */ - - -/*****************************************************************************/ -/* send one config line to the card and return 0 if successful, otherwise a */ -/* negative error code. */ -/* The function works with timeouts perhaps not giving the greatest speed */ -/* sending the line, but this should be meaningless because only some lines */ -/* are to be sent and this happens very seldom. */ -/*****************************************************************************/ -int -hysdn_tx_cfgline(hysdn_card *card, unsigned char *line, unsigned short chan) -{ - int cnt = 50; /* timeout intervalls */ - unsigned long flags; - - if (card->debug_flags & LOG_SCHED_ASYN) - hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1); - - while (card->async_busy) { - - if (card->debug_flags & LOG_SCHED_ASYN) - hysdn_addlog(card, "async tx-cfg delayed"); - - msleep_interruptible(20); /* Timeout 20ms */ - if (!--cnt) - return (-ERR_ASYNC_TIME); /* timed out */ - } /* wait for buffer to become free */ - - spin_lock_irqsave(&card->hysdn_lock, flags); - strcpy(card->async_data, line); - card->async_len = strlen(line) + 1; - card->async_channel = chan; - card->async_busy = 1; /* request transfer */ - - /* now queue the task */ - schedule_work(&card->irq_queue); - spin_unlock_irqrestore(&card->hysdn_lock, flags); - - if (card->debug_flags & LOG_SCHED_ASYN) - hysdn_addlog(card, "async tx-cfg data queued"); - - cnt++; /* short delay */ - - while (card->async_busy) { - - if (card->debug_flags & LOG_SCHED_ASYN) - hysdn_addlog(card, "async tx-cfg waiting for tx-ready"); - - msleep_interruptible(20); /* Timeout 20ms */ - if (!--cnt) - return (-ERR_ASYNC_TIME); /* timed out */ - } /* wait for buffer to become free again */ - - if (card->debug_flags & LOG_SCHED_ASYN) - hysdn_addlog(card, "async tx-cfg data send"); - - return (0); /* line send correctly */ -} /* hysdn_tx_cfgline */ diff --git a/drivers/staging/isdn/hysdn/ince1pc.h b/drivers/staging/isdn/hysdn/ince1pc.h deleted file mode 100644 index cab68361de65..000000000000 --- a/drivers/staging/isdn/hysdn/ince1pc.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Linux driver for HYSDN cards - * common definitions for both sides of the bus: - * - conventions both spoolers must know - * - channel numbers agreed upon - * - * Author M. Steinkopf - * Copyright 1999 by M. Steinkopf - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#ifndef __INCE1PC_H__ -#define __INCE1PC_H__ - -/* basic scalar definitions have same meanning, - * but their declaration location depends on environment - */ - -/*--------------------------------------channel numbers---------------------*/ -#define CHAN_SYSTEM 0x0001 /* system channel (spooler to spooler) */ -#define CHAN_ERRLOG 0x0005 /* error logger */ -#define CHAN_CAPI 0x0064 /* CAPI interface */ -#define CHAN_NDIS_DATA 0x1001 /* NDIS data transfer */ - -/*--------------------------------------POF ready msg-----------------------*/ -/* NOTE: after booting POF sends system ready message to PC: */ -#define RDY_MAGIC 0x52535953UL /* 'SYSR' reversed */ -#define RDY_MAGIC_SIZE 4 /* size in bytes */ - -#define MAX_N_TOK_BYTES 255 - -#define MIN_RDY_MSG_SIZE RDY_MAGIC_SIZE -#define MAX_RDY_MSG_SIZE (RDY_MAGIC_SIZE + MAX_N_TOK_BYTES) - -#define SYSR_TOK_END 0 -#define SYSR_TOK_B_CHAN 1 /* nr. of B-Channels; DataLen=1; def: 2 */ -#define SYSR_TOK_FAX_CHAN 2 /* nr. of FAX Channels; DataLen=1; def: 0 */ -#define SYSR_TOK_MAC_ADDR 3 /* MAC-Address; DataLen=6; def: auto */ -#define SYSR_TOK_ESC 255 /* undefined data size yet */ -/* default values, if not corrected by token: */ -#define SYSR_TOK_B_CHAN_DEF 2 /* assume 2 B-Channels */ -#define SYSR_TOK_FAX_CHAN_DEF 1 /* assume 1 FAX Channel */ - -/* syntax of new SYSR token stream: - * channel: CHAN_SYSTEM - * msgsize: MIN_RDY_MSG_SIZE <= x <= MAX_RDY_MSG_SIZE - * RDY_MAGIC_SIZE <= x <= (RDY_MAGIC_SIZE+MAX_N_TOK_BYTES) - * msg : 0 1 2 3 {4 5 6 ..} - * S Y S R MAX_N_TOK_BYTES bytes of TokenStream - * - * TokenStream := empty - * | {NonEndTokenChunk} EndToken RotlCRC - * NonEndTokenChunk:= NonEndTokenId DataLen [Data] - * NonEndTokenId := 0x01 .. 0xFE 1 BYTE - * DataLen := 0x00 .. 0xFF 1 BYTE - * Data := DataLen bytes - * EndToken := 0x00 - * RotlCRC := special 1 byte CRC over all NonEndTokenChunk bytes - * s. RotlCRC algorithm - * - * RotlCRC algorithm: - * ucSum= 0 1 unsigned char - * for all NonEndTokenChunk bytes: - * ROTL(ucSum,1) rotate left by 1 - * ucSum += Char; add current byte with swap around - * RotlCRC= ~ucSum; invert all bits for result - * - * note: - * - for 16-bit FIFO add padding 0 byte to achieve even token data bytes! - */ - -/*--------------------------------------error logger------------------------*/ -/* note: pof needs final 0 ! */ -#define ERRLOG_CMD_REQ "ERRLOG ON" -#define ERRLOG_CMD_REQ_SIZE 10 /* with final 0 byte ! */ -#define ERRLOG_CMD_STOP "ERRLOG OFF" -#define ERRLOG_CMD_STOP_SIZE 11 /* with final 0 byte ! */ - -#define ERRLOG_ENTRY_SIZE 64 /* sizeof(tErrLogEntry) */ - /* remaining text size = 55 */ -#define ERRLOG_TEXT_SIZE (ERRLOG_ENTRY_SIZE - 2 * 4 - 1) - -typedef struct ErrLogEntry_tag { - - /*00 */ unsigned long ulErrType; - - /*04 */ unsigned long ulErrSubtype; - - /*08 */ unsigned char ucTextSize; - - /*09 */ unsigned char ucText[ERRLOG_TEXT_SIZE]; - /* ASCIIZ of len ucTextSize-1 */ - -/*40 */ -} tErrLogEntry; - - -#if defined(__TURBOC__) -#if sizeof(tErrLogEntry) != ERRLOG_ENTRY_SIZE -#error size of tErrLogEntry != ERRLOG_ENTRY_SIZE -#endif /* */ -#endif /* */ - -/*--------------------------------------DPRAM boot spooler------------------*/ -/* this is the struture used between pc and - * hyperstone to exchange boot data - */ -#define DPRAM_SPOOLER_DATA_SIZE 0x20 -typedef struct DpramBootSpooler_tag { - - /*00 */ unsigned char Len; - - /*01 */ volatile unsigned char RdPtr; - - /*02 */ unsigned char WrPtr; - - /*03 */ unsigned char Data[DPRAM_SPOOLER_DATA_SIZE]; - -/*23 */ -} tDpramBootSpooler; - - -#define DPRAM_SPOOLER_MIN_SIZE 5 /* Len+RdPtr+Wrptr+2*data */ -#define DPRAM_SPOOLER_DEF_SIZE 0x23 /* current default size */ - -/*--------------------------------------HYCARD/ERGO DPRAM SoftUart----------*/ -/* at DPRAM offset 0x1C00: */ -#define SIZE_RSV_SOFT_UART 0x1B0 /* 432 bytes reserved for SoftUart */ - - -#endif /* __INCE1PC_H__ */ diff --git a/include/linux/b1pcmcia.h b/include/linux/b1pcmcia.h deleted file mode 100644 index 12a867c6061e..000000000000 --- a/include/linux/b1pcmcia.h +++ /dev/null @@ -1,21 +0,0 @@ -/* $Id: b1pcmcia.h,v 1.1.8.2 2001/09/23 22:25:05 kai Exp $ - * - * Exported functions of module b1pcmcia to be called by - * avm_cs card services module. - * - * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#ifndef _B1PCMCIA_H_ -#define _B1PCMCIA_H_ - -int b1pcmcia_addcard_b1(unsigned int port, unsigned irq); -int b1pcmcia_addcard_m1(unsigned int port, unsigned irq); -int b1pcmcia_addcard_m2(unsigned int port, unsigned irq); -int b1pcmcia_delcard(unsigned int port, unsigned irq); - -#endif /* _B1PCMCIA_H_ */ diff --git a/include/uapi/linux/gigaset_dev.h b/include/uapi/linux/gigaset_dev.h deleted file mode 100644 index 279551af8ebf..000000000000 --- a/include/uapi/linux/gigaset_dev.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ -/* - * interface to user space for the gigaset driver - * - * Copyright (c) 2004 by Hansjoerg Lipp - * - * ===================================================================== - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * ===================================================================== - */ - -#ifndef GIGASET_INTERFACE_H -#define GIGASET_INTERFACE_H - -#include - -/* The magic IOCTL value for this interface. */ -#define GIGASET_IOCTL 0x47 - -/* enable/disable device control via character device (lock out ISDN subsys) */ -#define GIGASET_REDIR _IOWR(GIGASET_IOCTL, 0, int) - -/* enable adapter configuration mode (M10x only) */ -#define GIGASET_CONFIG _IOWR(GIGASET_IOCTL, 1, int) - -/* set break characters (M105 only) */ -#define GIGASET_BRKCHARS _IOW(GIGASET_IOCTL, 2, unsigned char[6]) - -/* get version information selected by arg[0] */ -#define GIGASET_VERSION _IOWR(GIGASET_IOCTL, 3, unsigned[4]) -/* values for GIGASET_VERSION arg[0] */ -#define GIGVER_DRIVER 0 /* get driver version */ -#define GIGVER_COMPAT 1 /* get interface compatibility version */ -#define GIGVER_FWBASE 2 /* get base station firmware version */ - -#endif diff --git a/include/uapi/linux/hysdn_if.h b/include/uapi/linux/hysdn_if.h deleted file mode 100644 index 99f77c517e6d..000000000000 --- a/include/uapi/linux/hysdn_if.h +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* $Id: hysdn_if.h,v 1.1.8.3 2001/09/23 22:25:05 kai Exp $ - * - * Linux driver for HYSDN cards - * ioctl definitions shared by hynetmgr and driver. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -/****************/ -/* error values */ -/****************/ -#define ERR_NONE 0 /* no error occurred */ -#define ERR_ALREADY_BOOT 1000 /* we are already booting */ -#define EPOF_BAD_MAGIC 1001 /* bad magic in POF header */ -#define ERR_BOARD_DPRAM 1002 /* board DPRAM failed */ -#define EPOF_INTERNAL 1003 /* internal POF handler error */ -#define EPOF_BAD_IMG_SIZE 1004 /* POF boot image size invalid */ -#define ERR_BOOTIMG_FAIL 1005 /* 1. stage boot image did not start */ -#define ERR_BOOTSEQ_FAIL 1006 /* 2. stage boot seq handshake timeout */ -#define ERR_POF_TIMEOUT 1007 /* timeout waiting for card pof ready */ -#define ERR_NOT_BOOTED 1008 /* operation only allowed when booted */ -#define ERR_CONF_LONG 1009 /* conf line is too long */ -#define ERR_INV_CHAN 1010 /* invalid channel number */ -#define ERR_ASYNC_TIME 1011 /* timeout sending async data */ - - - - From f59aba2f75795e5b6a4f1aa31f3e20d7b71ca804 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 10 Dec 2019 21:59:16 +0100 Subject: [PATCH 061/353] isdn: capi: dead code removal The staging isdn drivers are gone, and CONFIG_BT_CMTP is now the only user. This means a lot of the code in the subsystem has no remaining callers and can be removed. Change the capi user space front-end to be part of kernelcapi, and the combined module to only be compiled if BT_CMTP is also enabled, then remove the interfaces that have no remaining callers. As the notifier list and the capi_drivers list have no callers outside of kcapi.c, the implementation gets much simpler. Some definitions from the include/linux/*.h headers are only needed internally and are moved to kcapi.h. Acked-by: David Miller Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20191210210455.3475361-2-arnd@arndb.de Signed-off-by: Greg Kroah-Hartman --- Documentation/isdn/interface_capi.rst | 71 ---- drivers/isdn/Makefile | 2 +- drivers/isdn/capi/Kconfig | 32 +- drivers/isdn/capi/Makefile | 18 +- drivers/isdn/capi/capi.c | 14 +- drivers/isdn/capi/capilib.c | 202 ------------ drivers/isdn/capi/capiutil.c | 231 +------------ drivers/isdn/capi/kcapi.c | 415 +---------------------- drivers/isdn/capi/kcapi.h | 149 ++++++++- drivers/isdn/capi/kcapi_proc.c | 34 +- include/linux/isdn/capilli.h | 18 - include/linux/isdn/capiutil.h | 456 -------------------------- include/linux/kernelcapi.h | 75 ----- include/uapi/linux/b1lli.h | 74 ----- 14 files changed, 182 insertions(+), 1609 deletions(-) delete mode 100644 drivers/isdn/capi/capilib.c delete mode 100644 include/uapi/linux/b1lli.h diff --git a/Documentation/isdn/interface_capi.rst b/Documentation/isdn/interface_capi.rst index 01a4b5ade9a4..fe2421444b76 100644 --- a/Documentation/isdn/interface_capi.rst +++ b/Documentation/isdn/interface_capi.rst @@ -26,13 +26,6 @@ This standard is freely available from https://www.capi.org. 2. Driver and Device Registration ================================= -CAPI drivers optionally register themselves with Kernel CAPI by calling the -Kernel CAPI function register_capi_driver() with a pointer to a struct -capi_driver. This structure must be filled with the name and revision of the -driver, and optionally a pointer to a callback function, add_card(). The -registration can be revoked by calling the function unregister_capi_driver() -with a pointer to the same struct capi_driver. - CAPI drivers must register each of the ISDN devices they control with Kernel CAPI by calling the Kernel CAPI function attach_capi_ctr() with a pointer to a struct capi_ctr before they can be used. This structure must be filled with @@ -89,9 +82,6 @@ register_capi_driver(): the name of the driver, as a zero-terminated ASCII string ``char revision[32]`` the revision number of the driver, as a zero-terminated ASCII string -``int (*add_card)(struct capi_driver *driver, capicardparams *data)`` - a callback function pointer (may be NULL) - 4.2 struct capi_ctr ------------------- @@ -178,12 +168,6 @@ to be set by the driver before calling attach_capi_ctr(): pointer to a callback function returning the entry for the device in the CAPI controller info table, /proc/capi/controller -``const struct file_operations *proc_fops`` - pointers to callback functions for the device's proc file - system entry, /proc/capi/controllers/; pointer to the device's - capi_ctr structure is available from struct proc_dir_entry::data - which is available from struct inode. - Note: Callback functions except send_message() are never called in interrupt context. @@ -267,25 +251,10 @@ _cmstruct alternative representation for CAPI parameters of type 'struct' _cmsg structure members. =========== ================================================================= -Functions capi_cmsg2message() and capi_message2cmsg() are provided to convert -messages between their transport encoding described in the CAPI 2.0 standard -and their _cmsg structure representation. Note that capi_cmsg2message() does -not know or check the size of its destination buffer. The caller must make -sure it is big enough to accommodate the resulting CAPI message. - 5. Lower Layer Interface Functions ================================== -(declared in ) - -:: - - void register_capi_driver(struct capi_driver *drvr) - void unregister_capi_driver(struct capi_driver *drvr) - -register/unregister a driver with Kernel CAPI - :: int attach_capi_ctr(struct capi_ctr *ctrlr) @@ -300,13 +269,6 @@ register/unregister a device (controller) with Kernel CAPI signal controller ready/not ready -:: - - void capi_ctr_suspend_output(struct capi_ctr *ctrlr) - void capi_ctr_resume_output(struct capi_ctr *ctrlr) - -signal suspend/resume - :: void capi_ctr_handle_message(struct capi_ctr * ctrlr, u16 applid, @@ -319,21 +281,6 @@ for forwarding to the specified application 6. Helper Functions and Macros ============================== -Library functions (from ): - -:: - - void capilib_new_ncci(struct list_head *head, u16 applid, - u32 ncci, u32 winsize) - void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci) - void capilib_release_appl(struct list_head *head, u16 applid) - void capilib_release(struct list_head *head) - void capilib_data_b3_conf(struct list_head *head, u16 applid, - u32 ncci, u16 msgid) - u16 capilib_data_b3_req(struct list_head *head, u16 applid, - u32 ncci, u16 msgid) - - Macros to extract/set element values from/in a CAPI message header (from ): @@ -357,24 +304,6 @@ CAPIMSG_DATALEN(m) CAPIMSG_SETDATALEN(m, len) Data Length (u16) Library functions for working with _cmsg structures (from ): -``unsigned capi_cmsg2message(_cmsg *cmsg, u8 *msg)`` - Assembles a CAPI 2.0 message from the parameters in ``*cmsg``, - storing the result in ``*msg``. - -``unsigned capi_message2cmsg(_cmsg *cmsg, u8 *msg)`` - Disassembles the CAPI 2.0 message in ``*msg``, storing the parameters - in ``*cmsg``. - -``unsigned capi_cmsg_header(_cmsg *cmsg, u16 ApplId, u8 Command, u8 Subcommand, u16 Messagenumber, u32 Controller)`` - Fills the header part and address field of the _cmsg structure ``*cmsg`` - with the given values, zeroing the remainder of the structure so only - parameters with non-default values need to be changed before sending - the message. - -``void capi_cmsg_answer(_cmsg *cmsg)`` - Sets the low bit of the Subcommand field in ``*cmsg``, thereby - converting ``_REQ`` to ``_CONF`` and ``_IND`` to ``_RESP``. - ``char *capi_cmd2str(u8 Command, u8 Subcommand)`` Returns the CAPI 2.0 message name corresponding to the given command and subcommand values, as a static ASCII string. The return value may diff --git a/drivers/isdn/Makefile b/drivers/isdn/Makefile index 63baf27a2c79..d14334f4007e 100644 --- a/drivers/isdn/Makefile +++ b/drivers/isdn/Makefile @@ -3,6 +3,6 @@ # Object files in subdirectories -obj-$(CONFIG_ISDN_CAPI) += capi/ +obj-$(CONFIG_BT_CMTP) += capi/ obj-$(CONFIG_MISDN) += mISDN/ obj-$(CONFIG_ISDN) += hardware/ diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig index 573fea5500ce..cc408ad9aafb 100644 --- a/drivers/isdn/capi/Kconfig +++ b/drivers/isdn/capi/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -menuconfig ISDN_CAPI - tristate "CAPI 2.0 subsystem" +config ISDN_CAPI + def_bool ISDN && BT help This provides CAPI (the Common ISDN Application Programming Interface) Version 2.0, a standard making it easy for programs to @@ -15,42 +15,18 @@ menuconfig ISDN_CAPI See CONFIG_BT_CMTP for the last remaining regular driver in the kernel that uses the CAPI subsystem. -if ISDN_CAPI - config CAPI_TRACE - bool "CAPI trace support" - default y + def_bool BT_CMTP help If you say Y here, the kernelcapi driver can make verbose traces of CAPI messages. This feature can be enabled/disabled via IOCTL for every controller (default disabled). - This will increase the size of the kernelcapi module by 20 KB. - If unsure, say Y. - -config ISDN_CAPI_CAPI20 - tristate "CAPI2.0 /dev/capi20 support" - help - This option will provide the CAPI 2.0 interface to userspace - applications via /dev/capi20. Applications should use the - standardized libcapi20 to access this functionality. You should say - Y/M here. config ISDN_CAPI_MIDDLEWARE - bool "CAPI2.0 Middleware support" - depends on ISDN_CAPI_CAPI20 && TTY + def_bool BT_CMTP && TTY help This option will enhance the capabilities of the /dev/capi20 interface. It will provide a means of moving a data connection, established via the usual /dev/capi20 interface to a special tty device. If you want to use pppd with pppdcapiplugin to dial up to your ISP, say Y here. - -config ISDN_CAPI_CAPIDRV_VERBOSE - bool "Verbose reason code reporting" - depends on ISDN_CAPI_CAPIDRV - help - If you say Y here, the capidrv interface will give verbose reasons - for disconnecting. This will increase the size of the kernel by 7 KB. - If unsure, say N. - -endif diff --git a/drivers/isdn/capi/Makefile b/drivers/isdn/capi/Makefile index d299f3e75f89..352217ebabd8 100644 --- a/drivers/isdn/capi/Makefile +++ b/drivers/isdn/capi/Makefile @@ -1,17 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -# Makefile for the CAPI subsystem. +# Makefile for the CAPI subsystem used by BT_CMTP -# Ordering constraints: kernelcapi.o first - -# Each configuration option enables a list of files. - -obj-$(CONFIG_ISDN_CAPI) += kernelcapi.o -obj-$(CONFIG_ISDN_CAPI_CAPI20) += capi.o -obj-$(CONFIG_ISDN_CAPI_CAPIDRV) += capidrv.o - -# Multipart objects. - -kernelcapi-y := kcapi.o capiutil.o capilib.o -kernelcapi-$(CONFIG_PROC_FS) += kcapi_proc.o - -ccflags-y += -I$(srctree)/$(src)/../include -I$(srctree)/$(src)/../include/uapi +obj-$(CONFIG_BT_CMTP) += kernelcapi.o +kernelcapi-y := kcapi.o capiutil.o capi.o kcapi_proc.o diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 1675da34239b..85767f52fe3c 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -39,7 +39,9 @@ #include #include -MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); +#include "kcapi.h" + +MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer and /dev/capi20 interface"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); @@ -1412,15 +1414,22 @@ static int __init capi_init(void) { const char *compileinfo; int major_ret; + int ret; + + ret = kcapi_init(); + if (ret) + return ret; major_ret = register_chrdev(capi_major, "capi20", &capi_fops); if (major_ret < 0) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); + kcapi_exit(); return major_ret; } capi_class = class_create(THIS_MODULE, "capi"); if (IS_ERR(capi_class)) { unregister_chrdev(capi_major, "capi20"); + kcapi_exit(); return PTR_ERR(capi_class); } @@ -1430,6 +1439,7 @@ static int __init capi_init(void) device_destroy(capi_class, MKDEV(capi_major, 0)); class_destroy(capi_class); unregister_chrdev(capi_major, "capi20"); + kcapi_exit(); return -ENOMEM; } @@ -1455,6 +1465,8 @@ static void __exit capi_exit(void) unregister_chrdev(capi_major, "capi20"); capinc_tty_exit(); + + kcapi_exit(); } module_init(capi_init); diff --git a/drivers/isdn/capi/capilib.c b/drivers/isdn/capi/capilib.c deleted file mode 100644 index a39ad3796bba..000000000000 --- a/drivers/isdn/capi/capilib.c +++ /dev/null @@ -1,202 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include -#include -#include -#include - -#define DBG(format, arg...) do { \ - printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \ - } while (0) - -struct capilib_msgidqueue { - struct capilib_msgidqueue *next; - u16 msgid; -}; - -struct capilib_ncci { - struct list_head list; - u16 applid; - u32 ncci; - u32 winsize; - int nmsg; - struct capilib_msgidqueue *msgidqueue; - struct capilib_msgidqueue *msgidlast; - struct capilib_msgidqueue *msgidfree; - struct capilib_msgidqueue msgidpool[CAPI_MAXDATAWINDOW]; -}; - -// --------------------------------------------------------------------------- -// NCCI Handling - -static inline void mq_init(struct capilib_ncci *np) -{ - u_int i; - np->msgidqueue = NULL; - np->msgidlast = NULL; - np->nmsg = 0; - memset(np->msgidpool, 0, sizeof(np->msgidpool)); - np->msgidfree = &np->msgidpool[0]; - for (i = 1; i < np->winsize; i++) { - np->msgidpool[i].next = np->msgidfree; - np->msgidfree = &np->msgidpool[i]; - } -} - -static inline int mq_enqueue(struct capilib_ncci *np, u16 msgid) -{ - struct capilib_msgidqueue *mq; - if ((mq = np->msgidfree) == NULL) - return 0; - np->msgidfree = mq->next; - mq->msgid = msgid; - mq->next = NULL; - if (np->msgidlast) - np->msgidlast->next = mq; - np->msgidlast = mq; - if (!np->msgidqueue) - np->msgidqueue = mq; - np->nmsg++; - return 1; -} - -static inline int mq_dequeue(struct capilib_ncci *np, u16 msgid) -{ - struct capilib_msgidqueue **pp; - for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) { - if ((*pp)->msgid == msgid) { - struct capilib_msgidqueue *mq = *pp; - *pp = mq->next; - if (mq == np->msgidlast) - np->msgidlast = NULL; - mq->next = np->msgidfree; - np->msgidfree = mq; - np->nmsg--; - return 1; - } - } - return 0; -} - -void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize) -{ - struct capilib_ncci *np; - - np = kmalloc(sizeof(*np), GFP_ATOMIC); - if (!np) { - printk(KERN_WARNING "capilib_new_ncci: no memory.\n"); - return; - } - if (winsize > CAPI_MAXDATAWINDOW) { - printk(KERN_ERR "capi_new_ncci: winsize %d too big\n", - winsize); - winsize = CAPI_MAXDATAWINDOW; - } - np->applid = applid; - np->ncci = ncci; - np->winsize = winsize; - mq_init(np); - list_add_tail(&np->list, head); - DBG("kcapi: appl %d ncci 0x%x up", applid, ncci); -} - -EXPORT_SYMBOL(capilib_new_ncci); - -void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci) -{ - struct list_head *l; - struct capilib_ncci *np; - - list_for_each(l, head) { - np = list_entry(l, struct capilib_ncci, list); - if (np->applid != applid) - continue; - if (np->ncci != ncci) - continue; - printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", applid, ncci); - list_del(&np->list); - kfree(np); - return; - } - printk(KERN_ERR "capilib_free_ncci: ncci 0x%x not found\n", ncci); -} - -EXPORT_SYMBOL(capilib_free_ncci); - -void capilib_release_appl(struct list_head *head, u16 applid) -{ - struct list_head *l, *n; - struct capilib_ncci *np; - - list_for_each_safe(l, n, head) { - np = list_entry(l, struct capilib_ncci, list); - if (np->applid != applid) - continue; - printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", applid, np->ncci); - list_del(&np->list); - kfree(np); - } -} - -EXPORT_SYMBOL(capilib_release_appl); - -void capilib_release(struct list_head *head) -{ - struct list_head *l, *n; - struct capilib_ncci *np; - - list_for_each_safe(l, n, head) { - np = list_entry(l, struct capilib_ncci, list); - printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", np->applid, np->ncci); - list_del(&np->list); - kfree(np); - } -} - -EXPORT_SYMBOL(capilib_release); - -u16 capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid) -{ - struct list_head *l; - struct capilib_ncci *np; - - list_for_each(l, head) { - np = list_entry(l, struct capilib_ncci, list); - if (np->applid != applid) - continue; - if (np->ncci != ncci) - continue; - - if (mq_enqueue(np, msgid) == 0) - return CAPI_SENDQUEUEFULL; - - return CAPI_NOERROR; - } - printk(KERN_ERR "capilib_data_b3_req: ncci 0x%x not found\n", ncci); - return CAPI_NOERROR; -} - -EXPORT_SYMBOL(capilib_data_b3_req); - -void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid) -{ - struct list_head *l; - struct capilib_ncci *np; - - list_for_each(l, head) { - np = list_entry(l, struct capilib_ncci, list); - if (np->applid != applid) - continue; - if (np->ncci != ncci) - continue; - - if (mq_dequeue(np, msgid) == 0) { - printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n", - msgid, ncci); - } - return; - } - printk(KERN_ERR "capilib_data_b3_conf: ncci 0x%x not found\n", ncci); -} - -EXPORT_SYMBOL(capilib_data_b3_conf); diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c index 9846d82eb097..f26bf3c66d7e 100644 --- a/drivers/isdn/capi/capiutil.c +++ b/drivers/isdn/capi/capiutil.c @@ -20,6 +20,8 @@ #include #include +#include "kcapi.h" + /* from CAPI2.0 DDK AVM Berlin GmbH */ typedef struct { @@ -245,190 +247,6 @@ static void jumpcstruct(_cmsg *cmsg) } } } -/*-------------------------------------------------------*/ -static void pars_2_message(_cmsg *cmsg) -{ - - for (; TYP != _CEND; cmsg->p++) { - switch (TYP) { - case _CBYTE: - byteTLcpy(cmsg->m + cmsg->l, OFF); - cmsg->l++; - break; - case _CWORD: - wordTLcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 2; - break; - case _CDWORD: - dwordTLcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 4; - break; - case _CSTRUCT: - if (*(u8 **) OFF == NULL) { - *(cmsg->m + cmsg->l) = '\0'; - cmsg->l++; - } else if (**(_cstruct *) OFF != 0xff) { - structTLcpy(cmsg->m + cmsg->l, *(_cstruct *) OFF, 1 + **(_cstruct *) OFF); - cmsg->l += 1 + **(_cstruct *) OFF; - } else { - _cstruct s = *(_cstruct *) OFF; - structTLcpy(cmsg->m + cmsg->l, s, 3 + *(u16 *) (s + 1)); - cmsg->l += 3 + *(u16 *) (s + 1); - } - break; - case _CMSTRUCT: -/*----- Metastruktur 0 -----*/ - if (*(_cmstruct *) OFF == CAPI_DEFAULT) { - *(cmsg->m + cmsg->l) = '\0'; - cmsg->l++; - jumpcstruct(cmsg); - } -/*----- Metastruktur wird composed -----*/ - else { - unsigned _l = cmsg->l; - unsigned _ls; - cmsg->l++; - cmsg->p++; - pars_2_message(cmsg); - _ls = cmsg->l - _l - 1; - if (_ls < 255) - (cmsg->m + _l)[0] = (u8) _ls; - else { - structTLcpyovl(cmsg->m + _l + 3, cmsg->m + _l + 1, _ls); - (cmsg->m + _l)[0] = 0xff; - wordTLcpy(cmsg->m + _l + 1, &_ls); - } - } - break; - } - } -} - -/** - * capi_cmsg2message() - assemble CAPI 2.0 message from _cmsg structure - * @cmsg: _cmsg structure - * @msg: buffer for assembled message - * - * Return value: 0 for success - */ - -unsigned capi_cmsg2message(_cmsg *cmsg, u8 *msg) -{ - cmsg->m = msg; - cmsg->l = 8; - cmsg->p = 0; - cmsg->par = capi_cmd2par(cmsg->Command, cmsg->Subcommand); - if (!cmsg->par) - return 1; /* invalid command/subcommand */ - - pars_2_message(cmsg); - - wordTLcpy(msg + 0, &cmsg->l); - byteTLcpy(cmsg->m + 4, &cmsg->Command); - byteTLcpy(cmsg->m + 5, &cmsg->Subcommand); - wordTLcpy(cmsg->m + 2, &cmsg->ApplId); - wordTLcpy(cmsg->m + 6, &cmsg->Messagenumber); - - return 0; -} - -/*-------------------------------------------------------*/ -static void message_2_pars(_cmsg *cmsg) -{ - for (; TYP != _CEND; cmsg->p++) { - - switch (TYP) { - case _CBYTE: - byteTRcpy(cmsg->m + cmsg->l, OFF); - cmsg->l++; - break; - case _CWORD: - wordTRcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 2; - break; - case _CDWORD: - dwordTRcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 4; - break; - case _CSTRUCT: - *(u8 **) OFF = cmsg->m + cmsg->l; - - if (cmsg->m[cmsg->l] != 0xff) - cmsg->l += 1 + cmsg->m[cmsg->l]; - else - cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1); - break; - case _CMSTRUCT: -/*----- Metastruktur 0 -----*/ - if (cmsg->m[cmsg->l] == '\0') { - *(_cmstruct *) OFF = CAPI_DEFAULT; - cmsg->l++; - jumpcstruct(cmsg); - } else { - unsigned _l = cmsg->l; - *(_cmstruct *) OFF = CAPI_COMPOSE; - cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1; - cmsg->p++; - message_2_pars(cmsg); - } - break; - } - } -} - -/** - * capi_message2cmsg() - disassemble CAPI 2.0 message into _cmsg structure - * @cmsg: _cmsg structure - * @msg: buffer for assembled message - * - * Return value: 0 for success - */ - -unsigned capi_message2cmsg(_cmsg *cmsg, u8 *msg) -{ - memset(cmsg, 0, sizeof(_cmsg)); - cmsg->m = msg; - cmsg->l = 8; - cmsg->p = 0; - byteTRcpy(cmsg->m + 4, &cmsg->Command); - byteTRcpy(cmsg->m + 5, &cmsg->Subcommand); - cmsg->par = capi_cmd2par(cmsg->Command, cmsg->Subcommand); - if (!cmsg->par) - return 1; /* invalid command/subcommand */ - - message_2_pars(cmsg); - - wordTRcpy(msg + 0, &cmsg->l); - wordTRcpy(cmsg->m + 2, &cmsg->ApplId); - wordTRcpy(cmsg->m + 6, &cmsg->Messagenumber); - - return 0; -} - -/** - * capi_cmsg_header() - initialize header part of _cmsg structure - * @cmsg: _cmsg structure - * @_ApplId: ApplID field value - * @_Command: Command field value - * @_Subcommand: Subcommand field value - * @_Messagenumber: Message Number field value - * @_Controller: Controller/PLCI/NCCI field value - * - * Return value: 0 for success - */ - -unsigned capi_cmsg_header(_cmsg *cmsg, u16 _ApplId, - u8 _Command, u8 _Subcommand, - u16 _Messagenumber, u32 _Controller) -{ - memset(cmsg, 0, sizeof(_cmsg)); - cmsg->ApplId = _ApplId; - cmsg->Command = _Command; - cmsg->Subcommand = _Subcommand; - cmsg->Messagenumber = _Messagenumber; - cmsg->adr.adrController = _Controller; - return 0; -} /*-------------------------------------------------------*/ @@ -561,8 +379,6 @@ static char *pnames[] = /*2f */ "Useruserdata" }; - - #include /*-------------------------------------------------------*/ @@ -800,37 +616,6 @@ _cdebbuf *capi_message2str(u8 *msg) return cdb; } -/** - * capi_cmsg2str() - format _cmsg structure for printing - * @cmsg: _cmsg structure - * - * Allocates a CAPI debug buffer and fills it with a printable representation - * of the CAPI 2.0 message stored in @cmsg by a previous call to - * capi_cmsg2message() or capi_message2cmsg(). - * Return value: allocated debug buffer, NULL on error - * The returned buffer should be freed by a call to cdebbuf_free() after use. - */ - -_cdebbuf *capi_cmsg2str(_cmsg *cmsg) -{ - _cdebbuf *cdb; - - if (!cmsg->m) - return NULL; /* no message */ - cdb = cdebbuf_alloc(); - if (!cdb) - return NULL; - cmsg->l = 8; - cmsg->p = 0; - cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n", - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - ((u16 *) cmsg->m)[1], - ((u16 *) cmsg->m)[3], - ((u16 *) cmsg->m)[0]); - cdb = protocol_message_2_pars(cdb, cmsg, 1); - return cdb; -} - int __init cdebug_init(void) { g_cmsg = kmalloc(sizeof(_cmsg), GFP_KERNEL); @@ -854,7 +639,7 @@ int __init cdebug_init(void) return 0; } -void __exit cdebug_exit(void) +void cdebug_exit(void) { if (g_debbuf) kfree(g_debbuf->buf); @@ -885,16 +670,8 @@ int __init cdebug_init(void) return 0; } -void __exit cdebug_exit(void) +void cdebug_exit(void) { } #endif - -EXPORT_SYMBOL(cdebbuf_free); -EXPORT_SYMBOL(capi_cmsg2message); -EXPORT_SYMBOL(capi_message2cmsg); -EXPORT_SYMBOL(capi_cmsg_header); -EXPORT_SYMBOL(capi_cmd2str); -EXPORT_SYMBOL(capi_cmsg2str); -EXPORT_SYMBOL(capi_message2str); diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index a4ceb61c5b60..7168778fbbe1 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -10,8 +10,6 @@ * */ -#define AVMB1_COMPAT - #include "kcapi.h" #include #include @@ -31,18 +29,12 @@ #include #include #include -#ifdef AVMB1_COMPAT -#include -#endif #include #include static int showcapimsgs = 0; static struct workqueue_struct *kcapi_wq; -MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); module_param(showcapimsgs, uint, 0); /* ------------------------------------------------------------- */ @@ -61,9 +53,6 @@ static char capi_manufakturer[64] = "AVM Berlin"; #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f) -LIST_HEAD(capi_drivers); -DEFINE_MUTEX(capi_drivers_lock); - struct capi_ctr *capi_controller[CAPI_MAXCONTR]; DEFINE_MUTEX(capi_controller_lock); @@ -71,8 +60,6 @@ struct capi20_appl *capi_applications[CAPI_MAXAPPL]; static int ncontrollers; -static BLOCKING_NOTIFIER_HEAD(ctr_notifier_list); - /* -------- controller ref counting -------------------------------------- */ static inline struct capi_ctr * @@ -200,8 +187,6 @@ static void notify_up(u32 contr) if (ap) register_appl(ctr, applid, &ap->rparam); } - - wake_up_interruptible_all(&ctr->state_wait_queue); } else printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); @@ -229,8 +214,6 @@ static void ctr_down(struct capi_ctr *ctr, int new_state) if (ap) capi_ctr_put(ctr); } - - wake_up_interruptible_all(&ctr->state_wait_queue); } static void notify_down(u32 contr) @@ -251,36 +234,23 @@ static void notify_down(u32 contr) mutex_unlock(&capi_controller_lock); } -static int -notify_handler(struct notifier_block *nb, unsigned long val, void *v) -{ - u32 contr = (long)v; - - switch (val) { - case CAPICTR_UP: - notify_up(contr); - break; - case CAPICTR_DOWN: - notify_down(contr); - break; - } - return NOTIFY_OK; -} - static void do_notify_work(struct work_struct *work) { struct capictr_event *event = container_of(work, struct capictr_event, work); - blocking_notifier_call_chain(&ctr_notifier_list, event->type, - (void *)(long)event->controller); + switch (event->type) { + case CAPICTR_UP: + notify_up(event->controller); + break; + case CAPICTR_DOWN: + notify_down(event->controller); + break; + } + kfree(event); } -/* - * The notifier will result in adding/deleteing of devices. Devices can - * only removed in user process, not in bh. - */ static int notify_push(unsigned int event_type, u32 controller) { struct capictr_event *event = kmalloc(sizeof(*event), GFP_ATOMIC); @@ -296,18 +266,6 @@ static int notify_push(unsigned int event_type, u32 controller) return 0; } -int register_capictr_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&ctr_notifier_list, nb); -} -EXPORT_SYMBOL_GPL(register_capictr_notifier); - -int unregister_capictr_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&ctr_notifier_list, nb); -} -EXPORT_SYMBOL_GPL(unregister_capictr_notifier); - /* -------- Receiver ------------------------------------------ */ static void recv_handler(struct work_struct *work) @@ -454,48 +412,6 @@ void capi_ctr_down(struct capi_ctr *ctr) EXPORT_SYMBOL(capi_ctr_down); -/** - * capi_ctr_suspend_output() - suspend controller - * @ctr: controller descriptor structure. - * - * Called by hardware driver to stop data flow. - * - * Note: The caller is responsible for synchronizing concurrent state changes - * as well as invocations of capi_ctr_handle_message. - */ - -void capi_ctr_suspend_output(struct capi_ctr *ctr) -{ - if (!ctr->blocked) { - printk(KERN_DEBUG "kcapi: controller [%03d] suspend\n", - ctr->cnr); - ctr->blocked = 1; - } -} - -EXPORT_SYMBOL(capi_ctr_suspend_output); - -/** - * capi_ctr_resume_output() - resume controller - * @ctr: controller descriptor structure. - * - * Called by hardware driver to resume data flow. - * - * Note: The caller is responsible for synchronizing concurrent state changes - * as well as invocations of capi_ctr_handle_message. - */ - -void capi_ctr_resume_output(struct capi_ctr *ctr) -{ - if (ctr->blocked) { - printk(KERN_DEBUG "kcapi: controller [%03d] resumed\n", - ctr->cnr); - ctr->blocked = 0; - } -} - -EXPORT_SYMBOL(capi_ctr_resume_output); - /* ------------------------------------------------------------- */ /** @@ -531,7 +447,6 @@ int attach_capi_ctr(struct capi_ctr *ctr) ctr->state = CAPI_CTR_DETECTED; ctr->blocked = 0; ctr->traceflag = showcapimsgs; - init_waitqueue_head(&ctr->state_wait_queue); sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr); ctr->procent = proc_create_single_data(ctr->procfn, 0, NULL, @@ -586,38 +501,6 @@ unlock_out: EXPORT_SYMBOL(detach_capi_ctr); -/** - * register_capi_driver() - register CAPI driver - * @driver: driver descriptor structure. - * - * Called by hardware driver to register itself with the CAPI subsystem. - */ - -void register_capi_driver(struct capi_driver *driver) -{ - mutex_lock(&capi_drivers_lock); - list_add_tail(&driver->list, &capi_drivers); - mutex_unlock(&capi_drivers_lock); -} - -EXPORT_SYMBOL(register_capi_driver); - -/** - * unregister_capi_driver() - unregister CAPI driver - * @driver: driver descriptor structure. - * - * Called by hardware driver to unregister itself from the CAPI subsystem. - */ - -void unregister_capi_driver(struct capi_driver *driver) -{ - mutex_lock(&capi_drivers_lock); - list_del(&driver->list); - mutex_unlock(&capi_drivers_lock); -} - -EXPORT_SYMBOL(unregister_capi_driver); - /* ------------------------------------------------------------- */ /* -------- CAPI2.0 Interface ---------------------------------- */ /* ------------------------------------------------------------- */ @@ -648,8 +531,6 @@ u16 capi20_isinstalled(void) return ret; } -EXPORT_SYMBOL(capi20_isinstalled); - /** * capi20_register() - CAPI 2.0 operation CAPI_REGISTER * @ap: CAPI application descriptor structure. @@ -711,8 +592,6 @@ u16 capi20_register(struct capi20_appl *ap) return CAPI_NOERROR; } -EXPORT_SYMBOL(capi20_register); - /** * capi20_release() - CAPI 2.0 operation CAPI_RELEASE * @ap: CAPI application descriptor structure. @@ -755,8 +634,6 @@ u16 capi20_release(struct capi20_appl *ap) return CAPI_NOERROR; } -EXPORT_SYMBOL(capi20_release); - /** * capi20_put_message() - CAPI 2.0 operation CAPI_PUT_MESSAGE * @ap: CAPI application descriptor structure. @@ -834,8 +711,6 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) return ctr->send_message(ctr, skb); } -EXPORT_SYMBOL(capi20_put_message); - /** * capi20_get_manufacturer() - CAPI 2.0 operation CAPI_GET_MANUFACTURER * @contr: controller number. @@ -869,8 +744,6 @@ u16 capi20_get_manufacturer(u32 contr, u8 *buf) return ret; } -EXPORT_SYMBOL(capi20_get_manufacturer); - /** * capi20_get_version() - CAPI 2.0 operation CAPI_GET_VERSION * @contr: controller number. @@ -904,8 +777,6 @@ u16 capi20_get_version(u32 contr, struct capi_version *verp) return ret; } -EXPORT_SYMBOL(capi20_get_version); - /** * capi20_get_serial() - CAPI 2.0 operation CAPI_GET_SERIAL_NUMBER * @contr: controller number. @@ -939,8 +810,6 @@ u16 capi20_get_serial(u32 contr, u8 *serial) return ret; } -EXPORT_SYMBOL(capi20_get_serial); - /** * capi20_get_profile() - CAPI 2.0 operation CAPI_GET_PROFILE * @contr: controller number. @@ -974,209 +843,6 @@ u16 capi20_get_profile(u32 contr, struct capi_profile *profp) return ret; } -EXPORT_SYMBOL(capi20_get_profile); - -/* Must be called with capi_controller_lock held. */ -static int wait_on_ctr_state(struct capi_ctr *ctr, unsigned int state) -{ - DEFINE_WAIT(wait); - int retval = 0; - - ctr = capi_ctr_get(ctr); - if (!ctr) - return -ESRCH; - - for (;;) { - prepare_to_wait(&ctr->state_wait_queue, &wait, - TASK_INTERRUPTIBLE); - - if (ctr->state == state) - break; - if (ctr->state == CAPI_CTR_DETACHED) { - retval = -ESRCH; - break; - } - if (signal_pending(current)) { - retval = -EINTR; - break; - } - - mutex_unlock(&capi_controller_lock); - schedule(); - mutex_lock(&capi_controller_lock); - } - finish_wait(&ctr->state_wait_queue, &wait); - - capi_ctr_put(ctr); - - return retval; -} - -#ifdef AVMB1_COMPAT -static int old_capi_manufacturer(unsigned int cmd, void __user *data) -{ - avmb1_loadandconfigdef ldef; - avmb1_extcarddef cdef; - avmb1_resetdef rdef; - capicardparams cparams; - struct capi_ctr *ctr; - struct capi_driver *driver = NULL; - capiloaddata ldata; - struct list_head *l; - int retval; - - switch (cmd) { - case AVMB1_ADDCARD: - case AVMB1_ADDCARD_WITH_TYPE: - if (cmd == AVMB1_ADDCARD) { - if ((retval = copy_from_user(&cdef, data, - sizeof(avmb1_carddef)))) - return -EFAULT; - cdef.cardtype = AVM_CARDTYPE_B1; - cdef.cardnr = 0; - } else { - if ((retval = copy_from_user(&cdef, data, - sizeof(avmb1_extcarddef)))) - return -EFAULT; - } - cparams.port = cdef.port; - cparams.irq = cdef.irq; - cparams.cardnr = cdef.cardnr; - - mutex_lock(&capi_drivers_lock); - - switch (cdef.cardtype) { - case AVM_CARDTYPE_B1: - list_for_each(l, &capi_drivers) { - driver = list_entry(l, struct capi_driver, list); - if (strcmp(driver->name, "b1isa") == 0) - break; - } - break; - case AVM_CARDTYPE_T1: - list_for_each(l, &capi_drivers) { - driver = list_entry(l, struct capi_driver, list); - if (strcmp(driver->name, "t1isa") == 0) - break; - } - break; - default: - driver = NULL; - break; - } - if (!driver) { - printk(KERN_ERR "kcapi: driver not loaded.\n"); - retval = -EIO; - } else if (!driver->add_card) { - printk(KERN_ERR "kcapi: driver has no add card function.\n"); - retval = -EIO; - } else - retval = driver->add_card(driver, &cparams); - - mutex_unlock(&capi_drivers_lock); - return retval; - - case AVMB1_LOAD: - case AVMB1_LOAD_AND_CONFIG: - - if (cmd == AVMB1_LOAD) { - if (copy_from_user(&ldef, data, - sizeof(avmb1_loaddef))) - return -EFAULT; - ldef.t4config.len = 0; - ldef.t4config.data = NULL; - } else { - if (copy_from_user(&ldef, data, - sizeof(avmb1_loadandconfigdef))) - return -EFAULT; - } - - mutex_lock(&capi_controller_lock); - - ctr = get_capi_ctr_by_nr(ldef.contr); - if (!ctr) { - retval = -EINVAL; - goto load_unlock_out; - } - - if (ctr->load_firmware == NULL) { - printk(KERN_DEBUG "kcapi: load: no load function\n"); - retval = -ESRCH; - goto load_unlock_out; - } - - if (ldef.t4file.len <= 0) { - printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); - retval = -EINVAL; - goto load_unlock_out; - } - if (ldef.t4file.data == NULL) { - printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); - retval = -EINVAL; - goto load_unlock_out; - } - - ldata.firmware.user = 1; - ldata.firmware.data = ldef.t4file.data; - ldata.firmware.len = ldef.t4file.len; - ldata.configuration.user = 1; - ldata.configuration.data = ldef.t4config.data; - ldata.configuration.len = ldef.t4config.len; - - if (ctr->state != CAPI_CTR_DETECTED) { - printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); - retval = -EBUSY; - goto load_unlock_out; - } - ctr->state = CAPI_CTR_LOADING; - - retval = ctr->load_firmware(ctr, &ldata); - if (retval) { - ctr->state = CAPI_CTR_DETECTED; - goto load_unlock_out; - } - - retval = wait_on_ctr_state(ctr, CAPI_CTR_RUNNING); - - load_unlock_out: - mutex_unlock(&capi_controller_lock); - return retval; - - case AVMB1_RESETCARD: - if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef))) - return -EFAULT; - - retval = 0; - - mutex_lock(&capi_controller_lock); - - ctr = get_capi_ctr_by_nr(rdef.contr); - if (!ctr) { - retval = -ESRCH; - goto reset_unlock_out; - } - - if (ctr->state == CAPI_CTR_DETECTED) - goto reset_unlock_out; - - if (ctr->reset_ctr == NULL) { - printk(KERN_DEBUG "kcapi: reset: no reset function\n"); - retval = -ESRCH; - goto reset_unlock_out; - } - - ctr->reset_ctr(ctr); - - retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED); - - reset_unlock_out: - mutex_unlock(&capi_controller_lock); - return retval; - } - return -EINVAL; -} -#endif - /** * capi20_manufacturer() - CAPI 2.0 operation CAPI_MANUFACTURER * @cmd: command. @@ -1192,14 +858,6 @@ int capi20_manufacturer(unsigned long cmd, void __user *data) int retval; switch (cmd) { -#ifdef AVMB1_COMPAT - case AVMB1_LOAD: - case AVMB1_LOAD_AND_CONFIG: - case AVMB1_RESETCARD: - case AVMB1_GET_CARDINFO: - case AVMB1_REMOVECARD: - return old_capi_manufacturer(cmd, data); -#endif case KCAPI_CMD_TRACE: { kcapi_flagdef fdef; @@ -1222,43 +880,6 @@ int capi20_manufacturer(unsigned long cmd, void __user *data) return retval; } - case KCAPI_CMD_ADDCARD: - { - struct list_head *l; - struct capi_driver *driver = NULL; - capicardparams cparams; - kcapi_carddef cdef; - - if ((retval = copy_from_user(&cdef, data, sizeof(cdef)))) - return -EFAULT; - - cparams.port = cdef.port; - cparams.irq = cdef.irq; - cparams.membase = cdef.membase; - cparams.cardnr = cdef.cardnr; - cparams.cardtype = 0; - cdef.driver[sizeof(cdef.driver) - 1] = 0; - - mutex_lock(&capi_drivers_lock); - - list_for_each(l, &capi_drivers) { - driver = list_entry(l, struct capi_driver, list); - if (strcmp(driver->name, cdef.driver) == 0) - break; - } - if (driver == NULL) { - printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n", - cdef.driver); - retval = -ESRCH; - } else if (!driver->add_card) { - printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver); - retval = -EIO; - } else - retval = driver->add_card(driver, &cparams); - - mutex_unlock(&capi_drivers_lock); - return retval; - } default: printk(KERN_ERR "kcapi: manufacturer command %lu unknown.\n", @@ -1269,8 +890,6 @@ int capi20_manufacturer(unsigned long cmd, void __user *data) return -EINVAL; } -EXPORT_SYMBOL(capi20_manufacturer); - /* ------------------------------------------------------------- */ /* -------- Init & Cleanup ------------------------------------- */ /* ------------------------------------------------------------- */ @@ -1279,12 +898,7 @@ EXPORT_SYMBOL(capi20_manufacturer); * init / exit functions */ -static struct notifier_block capictr_nb = { - .notifier_call = notify_handler, - .priority = INT_MAX, -}; - -static int __init kcapi_init(void) +int __init kcapi_init(void) { int err; @@ -1292,11 +906,8 @@ static int __init kcapi_init(void) if (!kcapi_wq) return -ENOMEM; - register_capictr_notifier(&capictr_nb); - err = cdebug_init(); if (err) { - unregister_capictr_notifier(&capictr_nb); destroy_workqueue(kcapi_wq); return err; } @@ -1305,14 +916,10 @@ static int __init kcapi_init(void) return 0; } -static void __exit kcapi_exit(void) +void kcapi_exit(void) { kcapi_proc_exit(); - unregister_capictr_notifier(&capictr_nb); cdebug_exit(); destroy_workqueue(kcapi_wq); } - -module_init(kcapi_init); -module_exit(kcapi_exit); diff --git a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h index 6d439f9a76b2..479623e1db2a 100644 --- a/drivers/isdn/capi/kcapi.h +++ b/drivers/isdn/capi/kcapi.h @@ -30,22 +30,153 @@ enum { CAPI_CTR_RUNNING = 3, }; -extern struct list_head capi_drivers; -extern struct mutex capi_drivers_lock; - extern struct capi_ctr *capi_controller[CAPI_MAXCONTR]; extern struct mutex capi_controller_lock; extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; -#ifdef CONFIG_PROC_FS - void kcapi_proc_init(void); void kcapi_proc_exit(void); -#else +struct capi20_appl { + u16 applid; + capi_register_params rparam; + void (*recv_message)(struct capi20_appl *ap, struct sk_buff *skb); + void *private; -static inline void kcapi_proc_init(void) { }; -static inline void kcapi_proc_exit(void) { }; + /* internal to kernelcapi.o */ + unsigned long nrecvctlpkt; + unsigned long nrecvdatapkt; + unsigned long nsentctlpkt; + unsigned long nsentdatapkt; + struct mutex recv_mtx; + struct sk_buff_head recv_queue; + struct work_struct recv_work; + int release_in_progress; +}; -#endif +u16 capi20_isinstalled(void); +u16 capi20_register(struct capi20_appl *ap); +u16 capi20_release(struct capi20_appl *ap); +u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb); +u16 capi20_get_manufacturer(u32 contr, u8 buf[CAPI_MANUFACTURER_LEN]); +u16 capi20_get_version(u32 contr, struct capi_version *verp); +u16 capi20_get_serial(u32 contr, u8 serial[CAPI_SERIAL_LEN]); +u16 capi20_get_profile(u32 contr, struct capi_profile *profp); +int capi20_manufacturer(unsigned long cmd, void __user *data); + +#define CAPICTR_UP 0 +#define CAPICTR_DOWN 1 + +int kcapi_init(void); +void kcapi_exit(void); + +/*----- basic-type definitions -----*/ + +typedef __u8 *_cstruct; + +typedef enum { + CAPI_COMPOSE, + CAPI_DEFAULT +} _cmstruct; + +/* + The _cmsg structure contains all possible CAPI 2.0 parameter. + All parameters are stored here first. The function CAPI_CMSG_2_MESSAGE + assembles the parameter and builds CAPI2.0 conform messages. + CAPI_MESSAGE_2_CMSG disassembles CAPI 2.0 messages and stores the + parameter in the _cmsg structure + */ + +typedef struct { + /* Header */ + __u16 ApplId; + __u8 Command; + __u8 Subcommand; + __u16 Messagenumber; + + /* Parameter */ + union { + __u32 adrController; + __u32 adrPLCI; + __u32 adrNCCI; + } adr; + + _cmstruct AdditionalInfo; + _cstruct B1configuration; + __u16 B1protocol; + _cstruct B2configuration; + __u16 B2protocol; + _cstruct B3configuration; + __u16 B3protocol; + _cstruct BC; + _cstruct BChannelinformation; + _cmstruct BProtocol; + _cstruct CalledPartyNumber; + _cstruct CalledPartySubaddress; + _cstruct CallingPartyNumber; + _cstruct CallingPartySubaddress; + __u32 CIPmask; + __u32 CIPmask2; + __u16 CIPValue; + __u32 Class; + _cstruct ConnectedNumber; + _cstruct ConnectedSubaddress; + __u32 Data; + __u16 DataHandle; + __u16 DataLength; + _cstruct FacilityConfirmationParameter; + _cstruct Facilitydataarray; + _cstruct FacilityIndicationParameter; + _cstruct FacilityRequestParameter; + __u16 FacilitySelector; + __u16 Flags; + __u32 Function; + _cstruct HLC; + __u16 Info; + _cstruct InfoElement; + __u32 InfoMask; + __u16 InfoNumber; + _cstruct Keypadfacility; + _cstruct LLC; + _cstruct ManuData; + __u32 ManuID; + _cstruct NCPI; + __u16 Reason; + __u16 Reason_B3; + __u16 Reject; + _cstruct Useruserdata; + + /* intern */ + unsigned l, p; + unsigned char *par; + __u8 *m; + + /* buffer to construct message */ + __u8 buf[180]; + +} _cmsg; + +/*-----------------------------------------------------------------------*/ + +/* + * Debugging / Tracing functions + */ + +char *capi_cmd2str(__u8 cmd, __u8 subcmd); + +typedef struct { + u_char *buf; + u_char *p; + size_t size; + size_t pos; +} _cdebbuf; + +#define CDEBUG_SIZE 1024 +#define CDEBUG_GSIZE 4096 + +void cdebbuf_free(_cdebbuf *cdb); +int cdebug_init(void); +void cdebug_exit(void); + +_cdebbuf *capi_message2str(__u8 *msg); diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index c94bd12c0f7c..2bffbb8bf271 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -192,37 +192,15 @@ static const struct seq_operations seq_applstats_ops = { // --------------------------------------------------------------------------- -static void *capi_driver_start(struct seq_file *seq, loff_t *pos) - __acquires(&capi_drivers_lock) +/* /proc/capi/drivers is always empty */ +static ssize_t empty_read(struct file *file, char __user *buf, + size_t size, loff_t *off) { - mutex_lock(&capi_drivers_lock); - return seq_list_start(&capi_drivers, *pos); -} - -static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos) -{ - return seq_list_next(v, &capi_drivers, pos); -} - -static void capi_driver_stop(struct seq_file *seq, void *v) - __releases(&capi_drivers_lock) -{ - mutex_unlock(&capi_drivers_lock); -} - -static int capi_driver_show(struct seq_file *seq, void *v) -{ - struct capi_driver *drv = list_entry(v, struct capi_driver, list); - - seq_printf(seq, "%-32s %s\n", drv->name, drv->revision); return 0; } -static const struct seq_operations seq_capi_driver_ops = { - .start = capi_driver_start, - .next = capi_driver_next, - .stop = capi_driver_stop, - .show = capi_driver_show, +static const struct file_operations empty_fops = { + .read = empty_read, }; // --------------------------------------------------------------------------- @@ -236,7 +214,7 @@ kcapi_proc_init(void) proc_create_seq("capi/contrstats", 0, NULL, &seq_contrstats_ops); proc_create_seq("capi/applications", 0, NULL, &seq_applications_ops); proc_create_seq("capi/applstats", 0, NULL, &seq_applstats_ops); - proc_create_seq("capi/driver", 0, NULL, &seq_capi_driver_ops); + proc_create("capi/driver", 0, NULL, &empty_fops); } void __exit diff --git a/include/linux/isdn/capilli.h b/include/linux/isdn/capilli.h index d75e1ad72964..12be09b6883b 100644 --- a/include/linux/isdn/capilli.h +++ b/include/linux/isdn/capilli.h @@ -69,7 +69,6 @@ struct capi_ctr { unsigned short state; /* controller state */ int blocked; /* output blocked */ int traceflag; /* capi trace */ - wait_queue_head_t state_wait_queue; struct proc_dir_entry *procent; char procfn[128]; @@ -80,8 +79,6 @@ int detach_capi_ctr(struct capi_ctr *); void capi_ctr_ready(struct capi_ctr * card); void capi_ctr_down(struct capi_ctr * card); -void capi_ctr_suspend_output(struct capi_ctr * card); -void capi_ctr_resume_output(struct capi_ctr * card); void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb); // --------------------------------------------------------------------------- @@ -91,23 +88,8 @@ struct capi_driver { char name[32]; /* driver name */ char revision[32]; - int (*add_card)(struct capi_driver *driver, capicardparams *data); - /* management information for kcapi */ struct list_head list; }; -void register_capi_driver(struct capi_driver *driver); -void unregister_capi_driver(struct capi_driver *driver); - -// --------------------------------------------------------------------------- -// library functions for use by hardware controller drivers - -void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize); -void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci); -void capilib_release_appl(struct list_head *head, u16 applid); -void capilib_release(struct list_head *head); -void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid); -u16 capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid); - #endif /* __CAPILLI_H__ */ diff --git a/include/linux/isdn/capiutil.h b/include/linux/isdn/capiutil.h index 44bd6046e6e2..953fd500dff7 100644 --- a/include/linux/isdn/capiutil.h +++ b/include/linux/isdn/capiutil.h @@ -57,460 +57,4 @@ static inline void capimsg_setu32(void *m, int off, __u32 val) #define CAPIMSG_SETCONTROL(m, contr) capimsg_setu32(m, 8, contr) #define CAPIMSG_SETDATALEN(m, len) capimsg_setu16(m, 16, len) -/*----- basic-type definitions -----*/ - -typedef __u8 *_cstruct; - -typedef enum { - CAPI_COMPOSE, - CAPI_DEFAULT -} _cmstruct; - -/* - The _cmsg structure contains all possible CAPI 2.0 parameter. - All parameters are stored here first. The function CAPI_CMSG_2_MESSAGE - assembles the parameter and builds CAPI2.0 conform messages. - CAPI_MESSAGE_2_CMSG disassembles CAPI 2.0 messages and stores the - parameter in the _cmsg structure - */ - -typedef struct { - /* Header */ - __u16 ApplId; - __u8 Command; - __u8 Subcommand; - __u16 Messagenumber; - - /* Parameter */ - union { - __u32 adrController; - __u32 adrPLCI; - __u32 adrNCCI; - } adr; - - _cmstruct AdditionalInfo; - _cstruct B1configuration; - __u16 B1protocol; - _cstruct B2configuration; - __u16 B2protocol; - _cstruct B3configuration; - __u16 B3protocol; - _cstruct BC; - _cstruct BChannelinformation; - _cmstruct BProtocol; - _cstruct CalledPartyNumber; - _cstruct CalledPartySubaddress; - _cstruct CallingPartyNumber; - _cstruct CallingPartySubaddress; - __u32 CIPmask; - __u32 CIPmask2; - __u16 CIPValue; - __u32 Class; - _cstruct ConnectedNumber; - _cstruct ConnectedSubaddress; - __u32 Data; - __u16 DataHandle; - __u16 DataLength; - _cstruct FacilityConfirmationParameter; - _cstruct Facilitydataarray; - _cstruct FacilityIndicationParameter; - _cstruct FacilityRequestParameter; - __u16 FacilitySelector; - __u16 Flags; - __u32 Function; - _cstruct HLC; - __u16 Info; - _cstruct InfoElement; - __u32 InfoMask; - __u16 InfoNumber; - _cstruct Keypadfacility; - _cstruct LLC; - _cstruct ManuData; - __u32 ManuID; - _cstruct NCPI; - __u16 Reason; - __u16 Reason_B3; - __u16 Reject; - _cstruct Useruserdata; - - /* intern */ - unsigned l, p; - unsigned char *par; - __u8 *m; - - /* buffer to construct message */ - __u8 buf[180]; - -} _cmsg; - -/* - * capi_cmsg2message() assembles the parameter from _cmsg to a CAPI 2.0 - * conform message - */ -unsigned capi_cmsg2message(_cmsg * cmsg, __u8 * msg); - -/* - * capi_message2cmsg disassembles a CAPI message an writes the parameter - * into _cmsg for easy access - */ -unsigned capi_message2cmsg(_cmsg * cmsg, __u8 * msg); - -/* - * capi_cmsg_header() fills the _cmsg structure with default values, so only - * parameter with non default values must be changed before sending the - * message. - */ -unsigned capi_cmsg_header(_cmsg * cmsg, __u16 _ApplId, - __u8 _Command, __u8 _Subcommand, - __u16 _Messagenumber, __u32 _Controller); - -/*-----------------------------------------------------------------------*/ - -/* - * Debugging / Tracing functions - */ - -char *capi_cmd2str(__u8 cmd, __u8 subcmd); - -typedef struct { - u_char *buf; - u_char *p; - size_t size; - size_t pos; -} _cdebbuf; - -#define CDEBUG_SIZE 1024 -#define CDEBUG_GSIZE 4096 - -void cdebbuf_free(_cdebbuf *cdb); -int cdebug_init(void); -void cdebug_exit(void); - -_cdebbuf *capi_cmsg2str(_cmsg *cmsg); -_cdebbuf *capi_message2str(__u8 *msg); - -/*-----------------------------------------------------------------------*/ - -static inline void capi_cmsg_answer(_cmsg * cmsg) -{ - cmsg->Subcommand |= 0x01; -} - -/*-----------------------------------------------------------------------*/ - -static inline void capi_fill_CONNECT_B3_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct NCPI) -{ - capi_cmsg_header(cmsg, ApplId, 0x82, 0x80, Messagenumber, adr); - cmsg->NCPI = NCPI; -} - -static inline void capi_fill_FACILITY_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 FacilitySelector, - _cstruct FacilityRequestParameter) -{ - capi_cmsg_header(cmsg, ApplId, 0x80, 0x80, Messagenumber, adr); - cmsg->FacilitySelector = FacilitySelector; - cmsg->FacilityRequestParameter = FacilityRequestParameter; -} - -static inline void capi_fill_INFO_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct CalledPartyNumber, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - capi_cmsg_header(cmsg, ApplId, 0x08, 0x80, Messagenumber, adr); - cmsg->CalledPartyNumber = CalledPartyNumber; - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_LISTEN_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u32 InfoMask, - __u32 CIPmask, - __u32 CIPmask2, - _cstruct CallingPartyNumber, - _cstruct CallingPartySubaddress) -{ - capi_cmsg_header(cmsg, ApplId, 0x05, 0x80, Messagenumber, adr); - cmsg->InfoMask = InfoMask; - cmsg->CIPmask = CIPmask; - cmsg->CIPmask2 = CIPmask2; - cmsg->CallingPartyNumber = CallingPartyNumber; - cmsg->CallingPartySubaddress = CallingPartySubaddress; -} - -static inline void capi_fill_ALERT_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - capi_cmsg_header(cmsg, ApplId, 0x01, 0x80, Messagenumber, adr); - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_CONNECT_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 CIPValue, - _cstruct CalledPartyNumber, - _cstruct CallingPartyNumber, - _cstruct CalledPartySubaddress, - _cstruct CallingPartySubaddress, - __u16 B1protocol, - __u16 B2protocol, - __u16 B3protocol, - _cstruct B1configuration, - _cstruct B2configuration, - _cstruct B3configuration, - _cstruct BC, - _cstruct LLC, - _cstruct HLC, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - - capi_cmsg_header(cmsg, ApplId, 0x02, 0x80, Messagenumber, adr); - cmsg->CIPValue = CIPValue; - cmsg->CalledPartyNumber = CalledPartyNumber; - cmsg->CallingPartyNumber = CallingPartyNumber; - cmsg->CalledPartySubaddress = CalledPartySubaddress; - cmsg->CallingPartySubaddress = CallingPartySubaddress; - cmsg->B1protocol = B1protocol; - cmsg->B2protocol = B2protocol; - cmsg->B3protocol = B3protocol; - cmsg->B1configuration = B1configuration; - cmsg->B2configuration = B2configuration; - cmsg->B3configuration = B3configuration; - cmsg->BC = BC; - cmsg->LLC = LLC; - cmsg->HLC = HLC; - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_DATA_B3_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u32 Data, - __u16 DataLength, - __u16 DataHandle, - __u16 Flags) -{ - - capi_cmsg_header(cmsg, ApplId, 0x86, 0x80, Messagenumber, adr); - cmsg->Data = Data; - cmsg->DataLength = DataLength; - cmsg->DataHandle = DataHandle; - cmsg->Flags = Flags; -} - -static inline void capi_fill_DISCONNECT_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - - capi_cmsg_header(cmsg, ApplId, 0x04, 0x80, Messagenumber, adr); - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_DISCONNECT_B3_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct NCPI) -{ - - capi_cmsg_header(cmsg, ApplId, 0x84, 0x80, Messagenumber, adr); - cmsg->NCPI = NCPI; -} - -static inline void capi_fill_MANUFACTURER_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u32 ManuID, - __u32 Class, - __u32 Function, - _cstruct ManuData) -{ - - capi_cmsg_header(cmsg, ApplId, 0xff, 0x80, Messagenumber, adr); - cmsg->ManuID = ManuID; - cmsg->Class = Class; - cmsg->Function = Function; - cmsg->ManuData = ManuData; -} - -static inline void capi_fill_RESET_B3_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct NCPI) -{ - - capi_cmsg_header(cmsg, ApplId, 0x87, 0x80, Messagenumber, adr); - cmsg->NCPI = NCPI; -} - -static inline void capi_fill_SELECT_B_PROTOCOL_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 B1protocol, - __u16 B2protocol, - __u16 B3protocol, - _cstruct B1configuration, - _cstruct B2configuration, - _cstruct B3configuration) -{ - - capi_cmsg_header(cmsg, ApplId, 0x41, 0x80, Messagenumber, adr); - cmsg->B1protocol = B1protocol; - cmsg->B2protocol = B2protocol; - cmsg->B3protocol = B3protocol; - cmsg->B1configuration = B1configuration; - cmsg->B2configuration = B2configuration; - cmsg->B3configuration = B3configuration; -} - -static inline void capi_fill_CONNECT_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 Reject, - __u16 B1protocol, - __u16 B2protocol, - __u16 B3protocol, - _cstruct B1configuration, - _cstruct B2configuration, - _cstruct B3configuration, - _cstruct ConnectedNumber, - _cstruct ConnectedSubaddress, - _cstruct LLC, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - capi_cmsg_header(cmsg, ApplId, 0x02, 0x83, Messagenumber, adr); - cmsg->Reject = Reject; - cmsg->B1protocol = B1protocol; - cmsg->B2protocol = B2protocol; - cmsg->B3protocol = B3protocol; - cmsg->B1configuration = B1configuration; - cmsg->B2configuration = B2configuration; - cmsg->B3configuration = B3configuration; - cmsg->ConnectedNumber = ConnectedNumber; - cmsg->ConnectedSubaddress = ConnectedSubaddress; - cmsg->LLC = LLC; - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_CONNECT_ACTIVE_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x03, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_CONNECT_B3_ACTIVE_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x83, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_CONNECT_B3_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 Reject, - _cstruct NCPI) -{ - capi_cmsg_header(cmsg, ApplId, 0x82, 0x83, Messagenumber, adr); - cmsg->Reject = Reject; - cmsg->NCPI = NCPI; -} - -static inline void capi_fill_CONNECT_B3_T90_ACTIVE_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x88, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_DATA_B3_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 DataHandle) -{ - - capi_cmsg_header(cmsg, ApplId, 0x86, 0x83, Messagenumber, adr); - cmsg->DataHandle = DataHandle; -} - -static inline void capi_fill_DISCONNECT_B3_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x84, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_DISCONNECT_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x04, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_FACILITY_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 FacilitySelector) -{ - - capi_cmsg_header(cmsg, ApplId, 0x80, 0x83, Messagenumber, adr); - cmsg->FacilitySelector = FacilitySelector; -} - -static inline void capi_fill_INFO_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x08, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_MANUFACTURER_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u32 ManuID, - __u32 Class, - __u32 Function, - _cstruct ManuData) -{ - - capi_cmsg_header(cmsg, ApplId, 0xff, 0x83, Messagenumber, adr); - cmsg->ManuID = ManuID; - cmsg->Class = Class; - cmsg->Function = Function; - cmsg->ManuData = ManuData; -} - -static inline void capi_fill_RESET_B3_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x87, 0x83, Messagenumber, adr); -} - #endif /* __CAPIUTIL_H__ */ diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h index 075fab5f92e1..94ba42bf9da1 100644 --- a/include/linux/kernelcapi.h +++ b/include/linux/kernelcapi.h @@ -10,46 +10,12 @@ #ifndef __KERNELCAPI_H__ #define __KERNELCAPI_H__ - #include #include #include #include #include -struct capi20_appl { - u16 applid; - capi_register_params rparam; - void (*recv_message)(struct capi20_appl *ap, struct sk_buff *skb); - void *private; - - /* internal to kernelcapi.o */ - unsigned long nrecvctlpkt; - unsigned long nrecvdatapkt; - unsigned long nsentctlpkt; - unsigned long nsentdatapkt; - struct mutex recv_mtx; - struct sk_buff_head recv_queue; - struct work_struct recv_work; - int release_in_progress; -}; - -u16 capi20_isinstalled(void); -u16 capi20_register(struct capi20_appl *ap); -u16 capi20_release(struct capi20_appl *ap); -u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb); -u16 capi20_get_manufacturer(u32 contr, u8 buf[CAPI_MANUFACTURER_LEN]); -u16 capi20_get_version(u32 contr, struct capi_version *verp); -u16 capi20_get_serial(u32 contr, u8 serial[CAPI_SERIAL_LEN]); -u16 capi20_get_profile(u32 contr, struct capi_profile *profp); -int capi20_manufacturer(unsigned long cmd, void __user *data); - -#define CAPICTR_UP 0 -#define CAPICTR_DOWN 1 - -int register_capictr_notifier(struct notifier_block *nb); -int unregister_capictr_notifier(struct notifier_block *nb); - #define CAPI_NOERROR 0x0000 #define CAPI_TOOMANYAPPLS 0x1001 @@ -76,45 +42,4 @@ int unregister_capictr_notifier(struct notifier_block *nb); #define CAPI_MSGCTRLERNOTSUPPORTEXTEQUIP 0x110a #define CAPI_MSGCTRLERONLYSUPPORTEXTEQUIP 0x110b -typedef enum { - CapiMessageNotSupportedInCurrentState = 0x2001, - CapiIllContrPlciNcci = 0x2002, - CapiNoPlciAvailable = 0x2003, - CapiNoNcciAvailable = 0x2004, - CapiNoListenResourcesAvailable = 0x2005, - CapiNoFaxResourcesAvailable = 0x2006, - CapiIllMessageParmCoding = 0x2007, -} RESOURCE_CODING_PROBLEM; - -typedef enum { - CapiB1ProtocolNotSupported = 0x3001, - CapiB2ProtocolNotSupported = 0x3002, - CapiB3ProtocolNotSupported = 0x3003, - CapiB1ProtocolParameterNotSupported = 0x3004, - CapiB2ProtocolParameterNotSupported = 0x3005, - CapiB3ProtocolParameterNotSupported = 0x3006, - CapiBProtocolCombinationNotSupported = 0x3007, - CapiNcpiNotSupported = 0x3008, - CapiCipValueUnknown = 0x3009, - CapiFlagsNotSupported = 0x300a, - CapiFacilityNotSupported = 0x300b, - CapiDataLengthNotSupportedByCurrentProtocol = 0x300c, - CapiResetProcedureNotSupportedByCurrentProtocol = 0x300d, - CapiTeiAssignmentFailed = 0x300e, -} REQUESTED_SERVICES_PROBLEM; - -typedef enum { - CapiSuccess = 0x0000, - CapiSupplementaryServiceNotSupported = 0x300e, - CapiRequestNotAllowedInThisState = 0x3010, -} SUPPLEMENTARY_SERVICE_INFO; - -typedef enum { - CapiProtocolErrorLayer1 = 0x3301, - CapiProtocolErrorLayer2 = 0x3302, - CapiProtocolErrorLayer3 = 0x3303, - CapiTimeOut = 0x3303, // SuppServiceReason - CapiCallGivenToOtherApplication = 0x3304, -} CAPI_REASON; - #endif /* __KERNELCAPI_H__ */ diff --git a/include/uapi/linux/b1lli.h b/include/uapi/linux/b1lli.h deleted file mode 100644 index 4ae6ac9950df..000000000000 --- a/include/uapi/linux/b1lli.h +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* $Id: b1lli.h,v 1.8.8.3 2001/09/23 22:25:05 kai Exp $ - * - * ISDN lowlevel-module for AVM B1-card. - * - * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#ifndef _B1LLI_H_ -#define _B1LLI_H_ -/* - * struct for loading t4 file - */ -typedef struct avmb1_t4file { - int len; - unsigned char *data; -} avmb1_t4file; - -typedef struct avmb1_loaddef { - int contr; - avmb1_t4file t4file; -} avmb1_loaddef; - -typedef struct avmb1_loadandconfigdef { - int contr; - avmb1_t4file t4file; - avmb1_t4file t4config; -} avmb1_loadandconfigdef; - -typedef struct avmb1_resetdef { - int contr; -} avmb1_resetdef; - -typedef struct avmb1_getdef { - int contr; - int cardtype; - int cardstate; -} avmb1_getdef; - -/* - * struct for adding new cards - */ -typedef struct avmb1_carddef { - int port; - int irq; -} avmb1_carddef; - -#define AVM_CARDTYPE_B1 0 -#define AVM_CARDTYPE_T1 1 -#define AVM_CARDTYPE_M1 2 -#define AVM_CARDTYPE_M2 3 - -typedef struct avmb1_extcarddef { - int port; - int irq; - int cardtype; - int cardnr; /* for HEMA/T1 */ -} avmb1_extcarddef; - -#define AVMB1_LOAD 0 /* load image to card */ -#define AVMB1_ADDCARD 1 /* add a new card - OBSOLETE */ -#define AVMB1_RESETCARD 2 /* reset a card */ -#define AVMB1_LOAD_AND_CONFIG 3 /* load image and config to card */ -#define AVMB1_ADDCARD_WITH_TYPE 4 /* add a new card, with cardtype */ -#define AVMB1_GET_CARDINFO 5 /* get cardtype */ -#define AVMB1_REMOVECARD 6 /* remove a card - OBSOLETE */ - -#define AVMB1_REGISTERCARD_IS_OBSOLETE - -#endif /* _B1LLI_H_ */ From b0ec7a44393e0d7a60878e2f56412072dd992724 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Mon, 25 Nov 2019 15:21:37 +0200 Subject: [PATCH 062/353] iio: adc: ad7887: Cleanup channel assignment The channels specification assignment in chip info was simplified. This patch makes supporting other devices by this driver easier. Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7887.c | 82 +++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c index 6223043e432b..c6a3428e950a 100644 --- a/drivers/iio/adc/ad7887.c +++ b/drivers/iio/adc/ad7887.c @@ -43,11 +43,17 @@ enum ad7887_channels { /** * struct ad7887_chip_info - chip specifc information * @int_vref_mv: the internal reference voltage - * @channel: channel specification + * @channels: channels specification + * @num_channels: number of channels + * @dual_channels: channels specification in dual mode + * @num_dual_channels: number of channels in dual mode */ struct ad7887_chip_info { u16 int_vref_mv; - struct iio_chan_spec channel[3]; + const struct iio_chan_spec *channels; + unsigned int num_channels; + const struct iio_chan_spec *dual_channels; + unsigned int num_dual_channels; }; struct ad7887_state { @@ -183,45 +189,43 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, return -EINVAL; } +#define AD7887_CHANNEL(x) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (x), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .address = (x), \ + .scan_index = (x), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 0, \ + .endianness = IIO_BE, \ + }, \ +} + +static const struct iio_chan_spec ad7887_channels[] = { + AD7887_CHANNEL(0), + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + +static const struct iio_chan_spec ad7887_dual_channels[] = { + AD7887_CHANNEL(0), + AD7887_CHANNEL(1), + IIO_CHAN_SOFT_TIMESTAMP(2), +}; static const struct ad7887_chip_info ad7887_chip_info_tbl[] = { /* * More devices added in future */ [ID_AD7887] = { - .channel[0] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), - .address = 1, - .scan_index = 1, - .scan_type = { - .sign = 'u', - .realbits = 12, - .storagebits = 16, - .shift = 0, - .endianness = IIO_BE, - }, - }, - .channel[1] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), - .address = 0, - .scan_index = 0, - .scan_type = { - .sign = 'u', - .realbits = 12, - .storagebits = 16, - .shift = 0, - .endianness = IIO_BE, - }, - }, - .channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2), + .channels = ad7887_channels, + .num_channels = ARRAY_SIZE(ad7887_channels), + .dual_channels = ad7887_dual_channels, + .num_dual_channels = ARRAY_SIZE(ad7887_dual_channels), .int_vref_mv = 2500, }, }; @@ -306,11 +310,11 @@ static int ad7887_probe(struct spi_device *spi) spi_message_init(&st->msg[AD7887_CH1]); spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]); - indio_dev->channels = st->chip_info->channel; - indio_dev->num_channels = 3; + indio_dev->channels = st->chip_info->dual_channels; + indio_dev->num_channels = st->chip_info->num_dual_channels; } else { - indio_dev->channels = &st->chip_info->channel[1]; - indio_dev->num_channels = 2; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; } ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, From 52241a082d6c08f4993180752ed5a12b39712f03 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 27 Nov 2019 21:17:38 +0100 Subject: [PATCH 063/353] iio: imu: inv_mpu6050: Select I2C_MUX again commit f7072198f217 ("iio: imu: Fix inv_mpu6050 dependencies") undid the explicit selection of I2C_MUX previously done by the driver, because I2C_MUX implicitly depended on HAS_IOMEM. However commit 93d710a65ef0 ("i2c: mux: fix up dependencies") cleared up the situation properly and drivers that need to select I2C_MUX can now do so again. It makes a lot of sense for a driver to select the driver infrastructure it needs so restore the natural order of things. Cc: Richard Weinberger Cc: Stephan Gerhold Signed-off-by: Linus Walleij Acked-by: Jean-Baptiste Maneyrol Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index 963a0cafe0cb..017bc0fcc365 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -10,7 +10,8 @@ config INV_MPU6050_IIO config INV_MPU6050_I2C tristate "Invensense MPU6050 devices (I2C)" - depends on I2C_MUX + depends on I2C + select I2C_MUX select INV_MPU6050_IIO select REGMAP_I2C help From d93813520df0ff6e0aec7c8859c56a659417f9b7 Mon Sep 17 00:00:00 2001 From: Marco Felsch Date: Fri, 29 Nov 2019 17:53:14 +0100 Subject: [PATCH 064/353] iio: adc: ad799x: add pm_ops to disable the device completely The device is always in a low-power state due to the hardware design. It wakes up upon a conversion request and goes back into the low-power state. The pm ops are added to disable the device completely and to free the regulator. Disbaling the device completely should be not that notable but freeing the regulator is important. Because if it is a shared power-rail the regulator won't be disabled during suspend-to-ram/disk and so all devices connected to that rail keeps on. Signed-off-by: Marco Felsch Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad799x.c | 66 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c index f658012baad8..ef013af1aec0 100644 --- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c @@ -167,6 +167,21 @@ static int ad799x_read_config(struct ad799x_state *st) } } +static int ad799x_update_config(struct ad799x_state *st, u16 config) +{ + int ret; + + ret = ad799x_write_config(st, config); + if (ret < 0) + return ret; + ret = ad799x_read_config(st); + if (ret < 0) + return ret; + st->config = ret; + + return 0; +} + /** * ad799x_trigger_handler() bh of trigger launched polling to ring buffer * @@ -808,13 +823,9 @@ static int ad799x_probe(struct i2c_client *client, indio_dev->channels = st->chip_config->channel; indio_dev->num_channels = chip_info->num_channels; - ret = ad799x_write_config(st, st->chip_config->default_config); - if (ret < 0) + ret = ad799x_update_config(st, st->chip_config->default_config); + if (ret) goto error_disable_vref; - ret = ad799x_read_config(st); - if (ret < 0) - goto error_disable_vref; - st->config = ret; ret = iio_triggered_buffer_setup(indio_dev, NULL, &ad799x_trigger_handler, NULL); @@ -864,6 +875,48 @@ static int ad799x_remove(struct i2c_client *client) return 0; } +static int __maybe_unused ad799x_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct ad799x_state *st = iio_priv(indio_dev); + + regulator_disable(st->vref); + regulator_disable(st->reg); + + return 0; +} + +static int __maybe_unused ad799x_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct ad799x_state *st = iio_priv(indio_dev); + int ret; + + ret = regulator_enable(st->reg); + if (ret) { + dev_err(dev, "Unable to enable vcc regulator\n"); + return ret; + } + ret = regulator_enable(st->vref); + if (ret) { + regulator_disable(st->reg); + dev_err(dev, "Unable to enable vref regulator\n"); + return ret; + } + + /* resync config */ + ret = ad799x_update_config(st, st->config); + if (ret) { + regulator_disable(st->vref); + regulator_disable(st->reg); + return ret; + } + + return 0; +} + +static SIMPLE_DEV_PM_OPS(ad799x_pm_ops, ad799x_suspend, ad799x_resume); + static const struct i2c_device_id ad799x_id[] = { { "ad7991", ad7991 }, { "ad7995", ad7995 }, @@ -881,6 +934,7 @@ MODULE_DEVICE_TABLE(i2c, ad799x_id); static struct i2c_driver ad799x_driver = { .driver = { .name = "ad799x", + .pm = &ad799x_pm_ops, }, .probe = ad799x_probe, .remove = ad799x_remove, From 2c289e63944467a41c6703f46bcf2f3340713510 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 2 Dec 2019 09:17:30 +0100 Subject: [PATCH 065/353] iio: ak8975: Convert to use GPIO descriptor The end-of-conversion (EOC) GPIO line is better to grab using a GPIO descriptor. We drop the pdata for this: clients using board files can use machine descriptor tables to pass this GPIO from static data. Cc: Stephan Gerhold Signed-off-by: Linus Walleij Reviewed-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 54 +++++++++---------------- include/linux/iio/magnetometer/ak8975.h | 2 - 2 files changed, 19 insertions(+), 37 deletions(-) diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 893bec5a0312..55cffaa82456 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -16,8 +16,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -360,7 +359,7 @@ struct ak8975_data { struct mutex lock; u8 asa[3]; long raw_to_gauss[3]; - int eoc_gpio; + struct gpio_desc *eoc_gpiod; int eoc_irq; wait_queue_head_t data_ready_queue; unsigned long flags; @@ -498,15 +497,13 @@ static int ak8975_setup_irq(struct ak8975_data *data) if (client->irq) irq = client->irq; else - irq = gpio_to_irq(data->eoc_gpio); + irq = gpiod_to_irq(data->eoc_gpiod); rc = devm_request_irq(&client->dev, irq, ak8975_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT, dev_name(&client->dev), data); if (rc < 0) { - dev_err(&client->dev, - "irq %d request failed, (gpio %d): %d\n", - irq, data->eoc_gpio, rc); + dev_err(&client->dev, "irq %d request failed: %d\n", irq, rc); return rc; } @@ -549,7 +546,7 @@ static int ak8975_setup(struct i2c_client *client) return ret; } - if (data->eoc_gpio > 0 || client->irq > 0) { + if (data->eoc_gpiod || client->irq > 0) { ret = ak8975_setup_irq(data); if (ret < 0) { dev_err(&client->dev, @@ -574,7 +571,7 @@ static int wait_conversion_complete_gpio(struct ak8975_data *data) /* Wait for the conversion to complete. */ while (timeout_ms) { msleep(AK8975_CONVERSION_DONE_POLL_TIME); - if (gpio_get_value(data->eoc_gpio)) + if (gpiod_get_value(data->eoc_gpiod)) break; timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME; } @@ -646,7 +643,7 @@ static int ak8975_start_read_axis(struct ak8975_data *data, /* Wait for the conversion to complete. */ if (data->eoc_irq) ret = wait_conversion_complete_interrupt(data); - else if (gpio_is_valid(data->eoc_gpio)) + else if (data->eoc_gpiod) ret = wait_conversion_complete_gpio(data); else ret = wait_conversion_complete_polled(data); @@ -856,36 +853,23 @@ static int ak8975_probe(struct i2c_client *client, { struct ak8975_data *data; struct iio_dev *indio_dev; - int eoc_gpio; + struct gpio_desc *eoc_gpiod; int err; const char *name = NULL; enum asahi_compass_chipset chipset = AK_MAX_TYPE; const struct ak8975_platform_data *pdata = dev_get_platdata(&client->dev); - /* Grab and set up the supplied GPIO. */ - if (pdata) - eoc_gpio = pdata->eoc_gpio; - else if (client->dev.of_node) - eoc_gpio = of_get_gpio(client->dev.of_node, 0); - else - eoc_gpio = -1; - - if (eoc_gpio == -EPROBE_DEFER) - return -EPROBE_DEFER; - - /* We may not have a GPIO based IRQ to scan, that is fine, we will - poll if so */ - if (gpio_is_valid(eoc_gpio)) { - err = devm_gpio_request_one(&client->dev, eoc_gpio, - GPIOF_IN, "ak_8975"); - if (err < 0) { - dev_err(&client->dev, - "failed to request GPIO %d, error %d\n", - eoc_gpio, err); - return err; - } - } + /* + * Grab and set up the supplied GPIO. + * We may not have a GPIO based IRQ to scan, that is fine, we will + * poll if so. + */ + eoc_gpiod = devm_gpiod_get_optional(&client->dev, NULL, GPIOD_IN); + if (IS_ERR(eoc_gpiod)) + return PTR_ERR(eoc_gpiod); + if (eoc_gpiod) + gpiod_set_consumer_name(eoc_gpiod, "ak_8975"); /* Register with IIO */ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); @@ -896,7 +880,7 @@ static int ak8975_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; - data->eoc_gpio = eoc_gpio; + data->eoc_gpiod = eoc_gpiod; data->eoc_irq = 0; if (!pdata) { diff --git a/include/linux/iio/magnetometer/ak8975.h b/include/linux/iio/magnetometer/ak8975.h index ac9366f807cb..df3697183800 100644 --- a/include/linux/iio/magnetometer/ak8975.h +++ b/include/linux/iio/magnetometer/ak8975.h @@ -6,11 +6,9 @@ /** * struct ak8975_platform_data - AK8975 magnetometer driver platform data - * @eoc_gpio: data ready event gpio * @orientation: mounting matrix relative to main hardware */ struct ak8975_platform_data { - int eoc_gpio; struct iio_mount_matrix orientation; }; From 757b4bcaa0d8fa74500b14b1655f6638ceafd056 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 1 Dec 2019 23:38:18 +0200 Subject: [PATCH 066/353] iio: imu: st_lsm6dsx: fix checkpatch warning Fix following checkpatch warning: CHECK: Alignment should match open parenthesis +static int st_lsm6dsx_read_event(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 11b2c7bc8041..a4ed72aef93e 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -1587,11 +1587,11 @@ static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, int state) } static int st_lsm6dsx_read_event(struct iio_dev *iio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int *val, int *val2) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) { struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); struct st_lsm6dsx_hw *hw = sensor->hw; From b4cc7e83dff352cb7ecdf561500d815bce0e3f5b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 2 Dec 2019 09:19:43 +0100 Subject: [PATCH 067/353] iio: as3935: Drop GPIO includes The driver includes and yet fails to use symbols from any of the include files, so drop these includes. Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/as3935.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index b591c63bd6c4..bac9a433dd19 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -22,8 +21,6 @@ #include #include #include -#include - #define AS3935_AFE_GAIN 0x00 #define AS3935_AFE_MASK 0x3F From cbe5997907235f71e6b0ab281b40e0cd151222d4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 2 Dec 2019 09:21:23 +0100 Subject: [PATCH 068/353] iio: si1145: Drop GPIO include The driver include yet does not use any of the symbols from the header, so drop the include. Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/light/si1145.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c index 982bba0c54e7..0476c2bc8138 100644 --- a/drivers/iio/light/si1145.c +++ b/drivers/iio/light/si1145.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include From 340db461f9acbd3621aad8f1ffca811847aa0165 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 2 Dec 2019 09:23:01 +0100 Subject: [PATCH 069/353] iio: ad2s1200: Drop legacy include This driver is using the GPIO descriptor API but yet includes the legacy header for no reason. Drop the surplus include. Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/resolver/ad2s1200.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/resolver/ad2s1200.c b/drivers/iio/resolver/ad2s1200.c index 17b89623418c..a391f46ee06b 100644 --- a/drivers/iio/resolver/ad2s1200.c +++ b/drivers/iio/resolver/ad2s1200.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include From 7544cd4c8ab72f9a18d3828a10524ce9740858a1 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 2 Dec 2019 09:24:52 +0100 Subject: [PATCH 070/353] iio: apds9960: Drop GPIO includes The driver includes and yet fails to use symbols from any of the include files, so drop these includes. Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/light/apds9960.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c index c5dfb9a6b5a1..52f86bc777dd 100644 --- a/drivers/iio/light/apds9960.c +++ b/drivers/iio/light/apds9960.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -24,7 +23,6 @@ #include #include #include -#include #define APDS9960_REGMAP_NAME "apds9960_regmap" #define APDS9960_DRV_NAME "apds9960" From dcfb6dbdfbe0ee209ec5e7b79ac45adce3a31e3a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 2 Dec 2019 09:26:03 +0100 Subject: [PATCH 071/353] iio: itg3200: Drop GPIO include The driver include yet does not use any of the symbols from the header, so drop the include. Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/itg3200_core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c index 981ae2291505..b3afa556f973 100644 --- a/drivers/iio/gyro/itg3200_core.c +++ b/drivers/iio/gyro/itg3200_core.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include From 4a89d2f47ccdce69597ba2f92e0b55c9a1f1d1ea Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 2 Dec 2019 09:38:30 +0100 Subject: [PATCH 072/353] iio: adf4350: Convert to use GPIO descriptor The lock detect GPIO line is better to grab using a GPIO descriptor. We drop the pdata for this: clients using board files can use machine descriptor tables to pass this GPIO from static data. Cc: Michael Hennerich Signed-off-by: Linus Walleij Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/frequency/adf4350.c | 30 +++++++-------------------- include/linux/iio/frequency/adf4350.h | 4 ---- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index ae0ca09ae062..1c2dc9b00f31 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -14,11 +14,10 @@ #include #include #include -#include +#include #include #include #include -#include #include #include @@ -34,6 +33,7 @@ enum { struct adf4350_state { struct spi_device *spi; struct regulator *reg; + struct gpio_desc *lock_detect_gpiod; struct adf4350_platform_data *pdata; struct clk *clk; unsigned long clkin; @@ -61,7 +61,6 @@ static struct adf4350_platform_data default_pdata = { .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | ADF4350_REG4_MUTE_TILL_LOCK_EN, - .gpio_lock_detect = -1, }; static int adf4350_sync_config(struct adf4350_state *st) @@ -317,8 +316,8 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev, (u64)st->fpfd; do_div(val, st->r1_mod * (1 << st->r4_rf_div_sel)); /* PLL unlocked? return error */ - if (gpio_is_valid(st->pdata->gpio_lock_detect)) - if (!gpio_get_value(st->pdata->gpio_lock_detect)) { + if (st->lock_detect_gpiod) + if (!gpiod_get_value(st->lock_detect_gpiod)) { dev_dbg(&st->spi->dev, "PLL un-locked\n"); ret = -EBUSY; } @@ -381,7 +380,6 @@ static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev) struct device_node *np = dev->of_node; struct adf4350_platform_data *pdata; unsigned int tmp; - int ret; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -401,12 +399,6 @@ static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev) of_property_read_u32(np, "adi,reference-div-factor", &tmp); pdata->ref_div_factor = tmp; - ret = of_get_gpio(np, 0); - if (ret < 0) - pdata->gpio_lock_detect = -1; - else - pdata->gpio_lock_detect = ret; - pdata->ref_doubler_en = of_property_read_bool(np, "adi,reference-doubler-enable"); pdata->ref_div2_en = of_property_read_bool(np, @@ -561,16 +553,10 @@ static int adf4350_probe(struct spi_device *spi) memset(st->regs_hw, 0xFF, sizeof(st->regs_hw)); - if (gpio_is_valid(pdata->gpio_lock_detect)) { - ret = devm_gpio_request(&spi->dev, pdata->gpio_lock_detect, - indio_dev->name); - if (ret) { - dev_err(&spi->dev, "fail to request lock detect GPIO-%d", - pdata->gpio_lock_detect); - goto error_disable_reg; - } - gpio_direction_input(pdata->gpio_lock_detect); - } + st->lock_detect_gpiod = devm_gpiod_get_optional(&spi->dev, NULL, + GPIOD_IN); + if (IS_ERR(st->lock_detect_gpiod)) + return PTR_ERR(st->lock_detect_gpiod); if (pdata->power_up_frequency) { ret = adf4350_set_freq(st, pdata->power_up_frequency); diff --git a/include/linux/iio/frequency/adf4350.h b/include/linux/iio/frequency/adf4350.h index ce9490bfeb89..de45cf2ee1e4 100644 --- a/include/linux/iio/frequency/adf4350.h +++ b/include/linux/iio/frequency/adf4350.h @@ -103,9 +103,6 @@ * @r2_user_settings: User defined settings for ADF4350/1 REGISTER_2. * @r3_user_settings: User defined settings for ADF4350/1 REGISTER_3. * @r4_user_settings: User defined settings for ADF4350/1 REGISTER_4. - * @gpio_lock_detect: Optional, if set with a valid GPIO number, - * pll lock state is tested upon read. - * If not used - set to -1. */ struct adf4350_platform_data { @@ -121,7 +118,6 @@ struct adf4350_platform_data { unsigned r2_user_settings; unsigned r3_user_settings; unsigned r4_user_settings; - int gpio_lock_detect; }; #endif /* IIO_PLL_ADF4350_H_ */ From b747e352499e4fca6e2e824852f5d91f4e29bf0e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 2 Dec 2019 09:58:48 +0100 Subject: [PATCH 073/353] iio: ad5592r: Drop surplus GPIO header This driver uses all the modern GPIO APIs from and so just drop the unused legacy header . Signed-off-by: Linus Walleij Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5592r-base.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c index 2d897e64c6a9..e2110113e884 100644 --- a/drivers/iio/dac/ad5592r-base.c +++ b/drivers/iio/dac/ad5592r-base.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include From 5750ebab14907f05aa9904ef2f3c1bb8dcb1fd2b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 2 Dec 2019 10:38:06 +0100 Subject: [PATCH 074/353] iio: ad7266: Convert to use GPIO descriptors The AD7266 have no in-tree users making use of the platform data mechanism to pass address GPIO lines when not using a fixed address, so we can easily convert this to use GPIO descriptors instead of the platform data integers currently passed. Lowercase the labels "ad0".."ad2" as this will make a better fit for platform descriptions like device tree that prefer lowercase names such as "ad0-gpios" rather than "AD0-gpios". Board files and other static users of this device can pass the same GPIO descriptors using machine descriptor tables if need be. Cc: Alison Schofield Cc: Lars-Peter Clausen Signed-off-by: Linus Walleij Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7266.c | 29 ++++++++++++---------------- include/linux/platform_data/ad7266.h | 3 --- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index c31b8eabb894..c8524f098883 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include @@ -34,7 +34,7 @@ struct ad7266_state { enum ad7266_range range; enum ad7266_mode mode; bool fixed_addr; - struct gpio gpios[3]; + struct gpio_desc *gpios[3]; /* * DMA (thus cache coherency maintenance) requires the @@ -117,7 +117,7 @@ static void ad7266_select_input(struct ad7266_state *st, unsigned int nr) } for (i = 0; i < 3; ++i) - gpio_set_value(st->gpios[i].gpio, (bool)(nr & BIT(i))); + gpiod_set_value(st->gpios[i], (bool)(nr & BIT(i))); } static int ad7266_update_scan_mode(struct iio_dev *indio_dev, @@ -376,7 +376,7 @@ static void ad7266_init_channels(struct iio_dev *indio_dev) } static const char * const ad7266_gpio_labels[] = { - "AD0", "AD1", "AD2", + "ad0", "ad1", "ad2", }; static int ad7266_probe(struct spi_device *spi) @@ -419,14 +419,14 @@ static int ad7266_probe(struct spi_device *spi) if (!st->fixed_addr) { for (i = 0; i < ARRAY_SIZE(st->gpios); ++i) { - st->gpios[i].gpio = pdata->addr_gpios[i]; - st->gpios[i].flags = GPIOF_OUT_INIT_LOW; - st->gpios[i].label = ad7266_gpio_labels[i]; + st->gpios[i] = devm_gpiod_get(&spi->dev, + ad7266_gpio_labels[i], + GPIOD_OUT_LOW); + if (IS_ERR(st->gpios[i])) { + ret = PTR_ERR(st->gpios[i]); + goto error_disable_reg; + } } - ret = gpio_request_array(st->gpios, - ARRAY_SIZE(st->gpios)); - if (ret) - goto error_disable_reg; } } else { st->fixed_addr = true; @@ -465,7 +465,7 @@ static int ad7266_probe(struct spi_device *spi) ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, &ad7266_trigger_handler, &iio_triggered_buffer_setup_ops); if (ret) - goto error_free_gpios; + goto error_disable_reg; ret = iio_device_register(indio_dev); if (ret) @@ -475,9 +475,6 @@ static int ad7266_probe(struct spi_device *spi) error_buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); -error_free_gpios: - if (!st->fixed_addr) - gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios)); error_disable_reg: if (!IS_ERR(st->reg)) regulator_disable(st->reg); @@ -492,8 +489,6 @@ static int ad7266_remove(struct spi_device *spi) iio_device_unregister(indio_dev); iio_triggered_buffer_cleanup(indio_dev); - if (!st->fixed_addr) - gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios)); if (!IS_ERR(st->reg)) regulator_disable(st->reg); diff --git a/include/linux/platform_data/ad7266.h b/include/linux/platform_data/ad7266.h index 7de6c16122df..f0652567afba 100644 --- a/include/linux/platform_data/ad7266.h +++ b/include/linux/platform_data/ad7266.h @@ -40,14 +40,11 @@ enum ad7266_mode { * @range: Reference voltage range the device is configured for * @mode: Sample mode the device is configured for * @fixed_addr: Whether the address pins are hard-wired - * @addr_gpios: GPIOs used for controlling the address pins, only used if - * fixed_addr is set to false. */ struct ad7266_platform_data { enum ad7266_range range; enum ad7266_mode mode; bool fixed_addr; - unsigned int addr_gpios[3]; }; #endif From 9eda18273754ca9bb7204786866666137c8e7d55 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 2 Dec 2019 10:18:37 +0100 Subject: [PATCH 075/353] iio: atlas-ph-sensor: Drop GPIO include The driver includes yet fails to use symbols from any the header so drop the include. Signed-off-by: Linus Walleij Reviewed-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/chemical/atlas-ph-sensor.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c index 6c175eb1c7a7..b7c20c74239b 100644 --- a/drivers/iio/chemical/atlas-ph-sensor.c +++ b/drivers/iio/chemical/atlas-ph-sensor.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include From 7c93f54e5bfb04ae90e330f8276c9311b03b1086 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Tue, 3 Dec 2019 12:17:13 +0200 Subject: [PATCH 076/353] iio: adc: Move AD7091R5 entry in a alphabetical order in Makefile Ad7091R5 was added in a non alphabetical order after AD7124 in Makefile and KConfig. This patch fixes that and place Ad7091R5 before AD7124. Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 14 +++++++------- drivers/iio/adc/Makefile | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 976567d4dbef..27bb4e56eaea 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -21,6 +21,13 @@ config AD_SIGMA_DELTA select IIO_BUFFER select IIO_TRIGGERED_BUFFER +config AD7091R5 + tristate "Analog Devices AD7091R5 ADC Driver" + depends on I2C + select REGMAP_I2C + help + Say yes here to build support for Analog Devices AD7091R-5 ADC. + config AD7124 tristate "Analog Devices AD7124 and similar sigma-delta ADCs driver" depends on SPI_MASTER @@ -32,13 +39,6 @@ config AD7124 To compile this driver as a module, choose M here: the module will be called ad7124. -config AD7091R5 - tristate "Analog Devices AD7091R5 ADC Driver" - depends on I2C - select REGMAP_I2C - help - Say yes here to build support for Analog Devices AD7091R-5 ADC. - config AD7266 tristate "Analog Devices AD7265/AD7266 ADC driver" depends on SPI_MASTER diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 84936ec24411..bf8354cdbc34 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -6,8 +6,8 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o -obj-$(CONFIG_AD7124) += ad7124.o obj-$(CONFIG_AD7091R5) += ad7091r5.o ad7091r-base.o +obj-$(CONFIG_AD7124) += ad7124.o obj-$(CONFIG_AD7266) += ad7266.o obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7292) += ad7292.o From 4cf01d6d4eea2e3841aeaa4cb977e73ab5efab10 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 2 Dec 2019 09:53:50 +0100 Subject: [PATCH 077/353] iio: ssp_sensors: Convert to use GPIO descriptors These three GPIO lines used by the Samsung sensor hub is pretty straight-forward to convert to use GPIO descriptors. Cc: Karol Wrona Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/common/ssp_sensors/ssp.h | 14 ++++++------ drivers/iio/common/ssp_sensors/ssp_dev.c | 29 ++++++++---------------- drivers/iio/common/ssp_sensors/ssp_spi.c | 8 +++---- 3 files changed, 20 insertions(+), 31 deletions(-) diff --git a/drivers/iio/common/ssp_sensors/ssp.h b/drivers/iio/common/ssp_sensors/ssp.h index 0a381bb1ae6f..abb832795619 100644 --- a/drivers/iio/common/ssp_sensors/ssp.h +++ b/drivers/iio/common/ssp_sensors/ssp.h @@ -7,7 +7,7 @@ #define __SSP_SENSORHUB_H__ #include -#include +#include #include #include #include @@ -168,9 +168,9 @@ struct ssp_sensorhub_info { * @fw_dl_state: firmware download state * @comm_lock: lock protecting the handshake * @pending_lock: lock protecting pending list and completion - * @mcu_reset_gpio: mcu reset line - * @ap_mcu_gpio: ap to mcu gpio line - * @mcu_ap_gpio: mcu to ap gpio line + * @mcu_reset_gpiod: mcu reset line + * @ap_mcu_gpiod: ap to mcu gpio line + * @mcu_ap_gpiod: mcu to ap gpio line * @pending_list: pending list for messages queued to be sent/read * @sensor_devs: registered IIO devices table * @enable_refcount: enable reference count for wdt (watchdog timer) @@ -212,9 +212,9 @@ struct ssp_data { struct mutex comm_lock; struct mutex pending_lock; - int mcu_reset_gpio; - int ap_mcu_gpio; - int mcu_ap_gpio; + struct gpio_desc *mcu_reset_gpiod; + struct gpio_desc *ap_mcu_gpiod; + struct gpio_desc *mcu_ap_gpiod; struct list_head pending_list; diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c index 9c70553994c6..a94dbcf491ce 100644 --- a/drivers/iio/common/ssp_sensors/ssp_dev.c +++ b/drivers/iio/common/ssp_sensors/ssp_dev.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include "ssp.h" @@ -61,9 +60,9 @@ static const struct mfd_cell sensorhub_sensor_devs[] = { static void ssp_toggle_mcu_reset_gpio(struct ssp_data *data) { - gpio_set_value(data->mcu_reset_gpio, 0); + gpiod_set_value(data->mcu_reset_gpiod, 0); usleep_range(1000, 1200); - gpio_set_value(data->mcu_reset_gpio, 1); + gpiod_set_value(data->mcu_reset_gpiod, 1); msleep(50); } @@ -441,7 +440,6 @@ MODULE_DEVICE_TABLE(of, ssp_of_match); static struct ssp_data *ssp_parse_dt(struct device *dev) { - int ret; struct ssp_data *data; struct device_node *node = dev->of_node; const struct of_device_id *match; @@ -450,26 +448,17 @@ static struct ssp_data *ssp_parse_dt(struct device *dev) if (!data) return NULL; - data->mcu_ap_gpio = of_get_named_gpio(node, "mcu-ap-gpios", 0); - if (data->mcu_ap_gpio < 0) + data->mcu_ap_gpiod = devm_gpiod_get(dev, "mcu-ap", GPIOD_IN); + if (IS_ERR(data->mcu_ap_gpiod)) return NULL; - data->ap_mcu_gpio = of_get_named_gpio(node, "ap-mcu-gpios", 0); - if (data->ap_mcu_gpio < 0) + data->ap_mcu_gpiod = devm_gpiod_get(dev, "ap-mcu", GPIOD_OUT_HIGH); + if (IS_ERR(data->ap_mcu_gpiod)) return NULL; - data->mcu_reset_gpio = of_get_named_gpio(node, "mcu-reset-gpios", 0); - if (data->mcu_reset_gpio < 0) - return NULL; - - ret = devm_gpio_request_one(dev, data->ap_mcu_gpio, GPIOF_OUT_INIT_HIGH, - "ap-mcu-gpios"); - if (ret) - return NULL; - - ret = devm_gpio_request_one(dev, data->mcu_reset_gpio, - GPIOF_OUT_INIT_HIGH, "mcu-reset-gpios"); - if (ret) + data->mcu_reset_gpiod = devm_gpiod_get(dev, "mcu-reset", + GPIOD_OUT_HIGH); + if (IS_ERR(data->mcu_reset_gpiod)) return NULL; match = of_match_node(ssp_of_match, node); diff --git a/drivers/iio/common/ssp_sensors/ssp_spi.c b/drivers/iio/common/ssp_sensors/ssp_spi.c index 7db3d5886e3e..4864c38b8d1c 100644 --- a/drivers/iio/common/ssp_sensors/ssp_spi.c +++ b/drivers/iio/common/ssp_sensors/ssp_spi.c @@ -155,9 +155,9 @@ static int ssp_check_lines(struct ssp_data *data, bool state) { int delay_cnt = 0; - gpio_set_value_cansleep(data->ap_mcu_gpio, state); + gpiod_set_value_cansleep(data->ap_mcu_gpiod, state); - while (gpio_get_value_cansleep(data->mcu_ap_gpio) != state) { + while (gpiod_get_value_cansleep(data->mcu_ap_gpiod) != state) { usleep_range(3000, 3500); if (data->shut_down || delay_cnt++ > 500) { @@ -165,7 +165,7 @@ static int ssp_check_lines(struct ssp_data *data, bool state) __func__, state); if (!state) - gpio_set_value_cansleep(data->ap_mcu_gpio, 1); + gpiod_set_value_cansleep(data->ap_mcu_gpiod, 1); return -ETIMEDOUT; } @@ -197,7 +197,7 @@ static int ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg, status = spi_write(data->spi, msg->buffer, SSP_HEADER_SIZE); if (status < 0) { - gpio_set_value_cansleep(data->ap_mcu_gpio, 1); + gpiod_set_value_cansleep(data->ap_mcu_gpiod, 1); dev_err(SSP_DEV, "%s spi_write fail\n", __func__); goto _error_locked; } From cc06e67d8fa55d000caeb4613e8873aed2c171ff Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Mon, 2 Dec 2019 10:02:19 +0100 Subject: [PATCH 078/353] iio: adc: stm32-adc: Add check on overrun interrupt Enable overrun interrupt on STM32 ADC. In case data register hasn't been read (by CPU or DMA), overrun condition is detected when there's new conversion data available. Stop grabbing data and log an error message. Use a threaded irq to avoid printing the error message from hard irq context. Signed-off-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-adc-core.c | 14 ++++---- drivers/iio/adc/stm32-adc-core.h | 9 ++++++ drivers/iio/adc/stm32-adc.c | 55 ++++++++++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 9 deletions(-) diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 6537f4f776c5..97655d7fc11a 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -280,21 +280,21 @@ out: static const struct stm32_adc_common_regs stm32f4_adc_common_regs = { .csr = STM32F4_ADC_CSR, .ccr = STM32F4_ADC_CCR, - .eoc1_msk = STM32F4_EOC1, - .eoc2_msk = STM32F4_EOC2, - .eoc3_msk = STM32F4_EOC3, + .eoc1_msk = STM32F4_EOC1 | STM32F4_OVR1, + .eoc2_msk = STM32F4_EOC2 | STM32F4_OVR2, + .eoc3_msk = STM32F4_EOC3 | STM32F4_OVR3, .ier = STM32F4_ADC_CR1, - .eocie_msk = STM32F4_EOCIE, + .eocie_msk = STM32F4_EOCIE | STM32F4_OVRIE, }; /* STM32H7 common registers definitions */ static const struct stm32_adc_common_regs stm32h7_adc_common_regs = { .csr = STM32H7_ADC_CSR, .ccr = STM32H7_ADC_CCR, - .eoc1_msk = STM32H7_EOC_MST, - .eoc2_msk = STM32H7_EOC_SLV, + .eoc1_msk = STM32H7_EOC_MST | STM32H7_OVR_MST, + .eoc2_msk = STM32H7_EOC_SLV | STM32H7_OVR_SLV, .ier = STM32H7_ADC_IER, - .eocie_msk = STM32H7_EOCIE, + .eocie_msk = STM32H7_EOCIE | STM32H7_OVRIE, }; static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = { diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h index 2579d514c2a3..2322809bfd2f 100644 --- a/drivers/iio/adc/stm32-adc-core.h +++ b/drivers/iio/adc/stm32-adc-core.h @@ -51,10 +51,12 @@ #define STM32F4_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x04) /* STM32F4_ADC_SR - bit fields */ +#define STM32F4_OVR BIT(5) #define STM32F4_STRT BIT(4) #define STM32F4_EOC BIT(1) /* STM32F4_ADC_CR1 - bit fields */ +#define STM32F4_OVRIE BIT(26) #define STM32F4_RES_SHIFT 24 #define STM32F4_RES_MASK GENMASK(25, 24) #define STM32F4_SCAN BIT(8) @@ -72,8 +74,11 @@ #define STM32F4_ADON BIT(0) /* STM32F4_ADC_CSR - bit fields */ +#define STM32F4_OVR3 BIT(21) #define STM32F4_EOC3 BIT(17) +#define STM32F4_OVR2 BIT(13) #define STM32F4_EOC2 BIT(9) +#define STM32F4_OVR1 BIT(5) #define STM32F4_EOC1 BIT(1) /* STM32F4_ADC_CCR - bit fields */ @@ -103,10 +108,12 @@ /* STM32H7_ADC_ISR - bit fields */ #define STM32MP1_VREGREADY BIT(12) +#define STM32H7_OVR BIT(4) #define STM32H7_EOC BIT(2) #define STM32H7_ADRDY BIT(0) /* STM32H7_ADC_IER - bit fields */ +#define STM32H7_OVRIE STM32H7_OVR #define STM32H7_EOCIE STM32H7_EOC /* STM32H7_ADC_CR - bit fields */ @@ -155,7 +162,9 @@ enum stm32h7_adc_dmngt { #define STM32H7_LINCALFACT_MASK GENMASK(29, 0) /* STM32H7_ADC_CSR - bit fields */ +#define STM32H7_OVR_SLV BIT(20) #define STM32H7_EOC_SLV BIT(18) +#define STM32H7_OVR_MST BIT(4) #define STM32H7_EOC_MST BIT(2) /* STM32H7_ADC_CCR - bit fields */ diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 3b291d72701c..5f05bf9f16ea 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -117,7 +117,9 @@ struct stm32_adc_regs { * struct stm32_adc_regspec - stm32 registers definition * @dr: data register offset * @ier_eoc: interrupt enable register & eocie bitfield + * @ier_ovr: interrupt enable register & overrun bitfield * @isr_eoc: interrupt status register & eoc bitfield + * @isr_ovr: interrupt status register & overrun bitfield * @sqr: reference to sequence registers array * @exten: trigger control register & bitfield * @extsel: trigger selection register & bitfield @@ -128,7 +130,9 @@ struct stm32_adc_regs { struct stm32_adc_regspec { const u32 dr; const struct stm32_adc_regs ier_eoc; + const struct stm32_adc_regs ier_ovr; const struct stm32_adc_regs isr_eoc; + const struct stm32_adc_regs isr_ovr; const struct stm32_adc_regs *sqr; const struct stm32_adc_regs exten; const struct stm32_adc_regs extsel; @@ -337,7 +341,9 @@ static const unsigned int stm32f4_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = { static const struct stm32_adc_regspec stm32f4_adc_regspec = { .dr = STM32F4_ADC_DR, .ier_eoc = { STM32F4_ADC_CR1, STM32F4_EOCIE }, + .ier_ovr = { STM32F4_ADC_CR1, STM32F4_OVRIE }, .isr_eoc = { STM32F4_ADC_SR, STM32F4_EOC }, + .isr_ovr = { STM32F4_ADC_SR, STM32F4_OVR }, .sqr = stm32f4_sq, .exten = { STM32F4_ADC_CR2, STM32F4_EXTEN_MASK, STM32F4_EXTEN_SHIFT }, .extsel = { STM32F4_ADC_CR2, STM32F4_EXTSEL_MASK, @@ -429,7 +435,9 @@ static const unsigned int stm32h7_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = { static const struct stm32_adc_regspec stm32h7_adc_regspec = { .dr = STM32H7_ADC_DR, .ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE }, + .ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE }, .isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC }, + .isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR }, .sqr = stm32h7_sq, .exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT }, .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK, @@ -506,6 +514,18 @@ static void stm32_adc_conv_irq_disable(struct stm32_adc *adc) adc->cfg->regs->ier_eoc.mask); } +static void stm32_adc_ovr_irq_enable(struct stm32_adc *adc) +{ + stm32_adc_set_bits(adc, adc->cfg->regs->ier_ovr.reg, + adc->cfg->regs->ier_ovr.mask); +} + +static void stm32_adc_ovr_irq_disable(struct stm32_adc *adc) +{ + stm32_adc_clr_bits(adc, adc->cfg->regs->ier_ovr.reg, + adc->cfg->regs->ier_ovr.mask); +} + static void stm32_adc_set_res(struct stm32_adc *adc) { const struct stm32_adc_regs *res = &adc->cfg->regs->res; @@ -1205,6 +1225,19 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, } } +static irqreturn_t stm32_adc_threaded_isr(int irq, void *data) +{ + struct stm32_adc *adc = data; + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + const struct stm32_adc_regspec *regs = adc->cfg->regs; + u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); + + if (status & regs->isr_ovr.mask) + dev_err(&indio_dev->dev, "Overrun, stopping: restart needed\n"); + + return IRQ_HANDLED; +} + static irqreturn_t stm32_adc_isr(int irq, void *data) { struct stm32_adc *adc = data; @@ -1212,6 +1245,19 @@ static irqreturn_t stm32_adc_isr(int irq, void *data) const struct stm32_adc_regspec *regs = adc->cfg->regs; u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); + if (status & regs->isr_ovr.mask) { + /* + * Overrun occurred on regular conversions: data for wrong + * channel may be read. Unconditionally disable interrupts + * to stop processing data and print error message. + * Restarting the capture can be done by disabling, then + * re-enabling it (e.g. write 0, then 1 to buffer/enable). + */ + stm32_adc_ovr_irq_disable(adc); + stm32_adc_conv_irq_disable(adc); + return IRQ_WAKE_THREAD; + } + if (status & regs->isr_eoc.mask) { /* Reading DR also clears EOC status flag */ adc->buffer[adc->bufi] = stm32_adc_readw(adc, regs->dr); @@ -1441,6 +1487,8 @@ static int __stm32_adc_buffer_postenable(struct iio_dev *indio_dev) /* Reset adc buffer index */ adc->bufi = 0; + stm32_adc_ovr_irq_enable(adc); + if (!adc->dma_chan) stm32_adc_conv_irq_enable(adc); @@ -1481,6 +1529,8 @@ static void __stm32_adc_buffer_predisable(struct iio_dev *indio_dev) if (!adc->dma_chan) stm32_adc_conv_irq_disable(adc); + stm32_adc_ovr_irq_disable(adc); + if (adc->dma_chan) dmaengine_terminate_sync(adc->dma_chan); @@ -1818,8 +1868,9 @@ static int stm32_adc_probe(struct platform_device *pdev) if (adc->irq < 0) return adc->irq; - ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr, - 0, pdev->name, adc); + ret = devm_request_threaded_irq(&pdev->dev, adc->irq, stm32_adc_isr, + stm32_adc_threaded_isr, + 0, pdev->name, adc); if (ret) { dev_err(&pdev->dev, "failed to request IRQ\n"); return ret; From 09a78f7dfac7b3a333fecd0839403f844b1a308e Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 2 Dec 2019 12:23:28 +0200 Subject: [PATCH 079/353] iio: humidity: hts221: move register definitions to sensor structs Move some register definitions to hts221_avg_list, hts221_avg_list and hts221_channels since they are used only there and simplify driver code Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/hts221_core.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/iio/humidity/hts221_core.c b/drivers/iio/humidity/hts221_core.c index 4922444771c6..9003671f14fb 100644 --- a/drivers/iio/humidity/hts221_core.c +++ b/drivers/iio/humidity/hts221_core.c @@ -24,13 +24,6 @@ #define HTS221_REG_CNTRL1_ADDR 0x20 #define HTS221_REG_CNTRL2_ADDR 0x21 -#define HTS221_REG_AVG_ADDR 0x10 -#define HTS221_REG_H_OUT_L 0x28 -#define HTS221_REG_T_OUT_L 0x2a - -#define HTS221_HUMIDITY_AVG_MASK 0x07 -#define HTS221_TEMP_AVG_MASK 0x38 - #define HTS221_ODR_MASK 0x03 #define HTS221_BDU_MASK BIT(2) #define HTS221_ENABLE_MASK BIT(7) @@ -66,8 +59,8 @@ static const struct hts221_odr hts221_odr_table[] = { static const struct hts221_avg hts221_avg_list[] = { { - .addr = HTS221_REG_AVG_ADDR, - .mask = HTS221_HUMIDITY_AVG_MASK, + .addr = 0x10, + .mask = 0x07, .avg_avl = { 4, /* 0.4 %RH */ 8, /* 0.3 %RH */ @@ -80,8 +73,8 @@ static const struct hts221_avg hts221_avg_list[] = { }, }, { - .addr = HTS221_REG_AVG_ADDR, - .mask = HTS221_TEMP_AVG_MASK, + .addr = 0x10, + .mask = 0x38, .avg_avl = { 2, /* 0.08 degC */ 4, /* 0.05 degC */ @@ -98,7 +91,7 @@ static const struct hts221_avg hts221_avg_list[] = { static const struct iio_chan_spec hts221_channels[] = { { .type = IIO_HUMIDITYRELATIVE, - .address = HTS221_REG_H_OUT_L, + .address = 0x28, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE) | @@ -114,7 +107,7 @@ static const struct iio_chan_spec hts221_channels[] = { }, { .type = IIO_TEMP, - .address = HTS221_REG_T_OUT_L, + .address = 0x2a, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE) | From 32bd4324601dc15a205f2b734e67ee5fd740ee66 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Wed, 4 Dec 2019 07:45:35 +0100 Subject: [PATCH 080/353] iio: adc: ti-ads7950: Fix a typo in an error message Fix a typo: s/get get/to get/ Signed-off-by: Christophe JAILLET Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-ads7950.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index 2e66e4d586ff..f9edc1207f75 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -602,7 +602,7 @@ static int ti_ads7950_probe(struct spi_device *spi) st->reg = devm_regulator_get(&spi->dev, "vref"); if (IS_ERR(st->reg)) { - dev_err(&spi->dev, "Failed get get regulator \"vref\"\n"); + dev_err(&spi->dev, "Failed to get regulator \"vref\"\n"); ret = PTR_ERR(st->reg); goto error_destroy_mutex; } From 0cd9ff1535f4339710dfd577a7d91b96fd4b423b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 5 Dec 2019 19:46:36 +0200 Subject: [PATCH 081/353] iio: adc: ti-ads1015: Get rid of legacy platform data Platform data is a legacy interface to supply device properties to the driver. In this case we even don't have in-kernel users for it. Just remove it for good. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-ads1015.c | 18 ++++++++---------- include/Kbuild | 1 - include/linux/platform_data/ads1015.h | 23 ----------------------- 3 files changed, 8 insertions(+), 34 deletions(-) delete mode 100644 include/linux/platform_data/ads1015.h diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index a550b132cfb7..3b123b4f0b99 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -21,8 +21,6 @@ #include #include -#include - #include #include #include @@ -33,6 +31,8 @@ #define ADS1015_DRV_NAME "ads1015" +#define ADS1015_CHANNELS 8 + #define ADS1015_CONV_REG 0x00 #define ADS1015_CFG_REG 0x01 #define ADS1015_LO_THRESH_REG 0x02 @@ -219,6 +219,12 @@ static const struct iio_event_spec ads1015_events[] = { .datasheet_name = "AIN"#_chan"-AIN"#_chan2, \ } +struct ads1015_channel_data { + bool enabled; + unsigned int pga; + unsigned int data_rate; +}; + struct ads1015_thresh_data { unsigned int comp_queue; int high_thresh; @@ -903,14 +909,6 @@ static void ads1015_get_channels_config(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); struct ads1015_data *data = iio_priv(indio_dev); - struct ads1015_platform_data *pdata = dev_get_platdata(&client->dev); - - /* prefer platform data */ - if (pdata) { - memcpy(data->channel_data, pdata->channel_data, - sizeof(data->channel_data)); - return; - } #ifdef CONFIG_OF if (!ads1015_get_channels_config_of(client)) diff --git a/include/Kbuild b/include/Kbuild index ffba79483cc5..498821e5d9ed 100644 --- a/include/Kbuild +++ b/include/Kbuild @@ -443,7 +443,6 @@ header-test- += linux/platform_data/ad7793.h header-test- += linux/platform_data/ad7887.h header-test- += linux/platform_data/adau17x1.h header-test- += linux/platform_data/adp8870.h -header-test- += linux/platform_data/ads1015.h header-test- += linux/platform_data/ads7828.h header-test- += linux/platform_data/apds990x.h header-test- += linux/platform_data/arm-ux500-pm.h diff --git a/include/linux/platform_data/ads1015.h b/include/linux/platform_data/ads1015.h deleted file mode 100644 index 4cc9ffcafcbf..000000000000 --- a/include/linux/platform_data/ads1015.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Platform Data for ADS1015 12-bit 4-input ADC - * (C) Copyright 2010 - * Dirk Eibach, Guntermann & Drunck GmbH - */ - -#ifndef LINUX_ADS1015_H -#define LINUX_ADS1015_H - -#define ADS1015_CHANNELS 8 - -struct ads1015_channel_data { - bool enabled; - unsigned int pga; - unsigned int data_rate; -}; - -struct ads1015_platform_data { - struct ads1015_channel_data channel_data[ADS1015_CHANNELS]; -}; - -#endif /* LINUX_ADS1015_H */ From 64335c4a6720017c45e0c07313a7a819e55a084a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 5 Dec 2019 19:46:37 +0200 Subject: [PATCH 082/353] iio: adc: ti-ads1015: Make use of device property API Make use of device property API in this driver so that both OF based system and ACPI based system can use this driver. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti-ads1015.c | 57 ++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index 3b123b4f0b99..5ea4f45d6bad 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -12,10 +12,10 @@ */ #include -#include #include #include #include +#include #include #include #include @@ -77,6 +77,7 @@ #define ADS1015_DEFAULT_CHAN 0 enum chip_ids { + ADSXXXX = 0, ADS1015, ADS1115, }; @@ -843,65 +844,58 @@ static const struct iio_info ads1115_info = { .attrs = &ads1115_attribute_group, }; -#ifdef CONFIG_OF -static int ads1015_get_channels_config_of(struct i2c_client *client) +static int ads1015_client_get_channels_config(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct ads1015_data *data = iio_priv(indio_dev); - struct device_node *node; + struct device *dev = &client->dev; + struct fwnode_handle *node; + int i = -1; - if (!client->dev.of_node || - !of_get_next_child(client->dev.of_node, NULL)) - return -EINVAL; - - for_each_child_of_node(client->dev.of_node, node) { + device_for_each_child_node(dev, node) { u32 pval; unsigned int channel; unsigned int pga = ADS1015_DEFAULT_PGA; unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE; - if (of_property_read_u32(node, "reg", &pval)) { - dev_err(&client->dev, "invalid reg on %pOF\n", - node); + if (fwnode_property_read_u32(node, "reg", &pval)) { + dev_err(dev, "invalid reg on %pfw\n", node); continue; } channel = pval; if (channel >= ADS1015_CHANNELS) { - dev_err(&client->dev, - "invalid channel index %d on %pOF\n", + dev_err(dev, "invalid channel index %d on %pfw\n", channel, node); continue; } - if (!of_property_read_u32(node, "ti,gain", &pval)) { + if (!fwnode_property_read_u32(node, "ti,gain", &pval)) { pga = pval; if (pga > 6) { - dev_err(&client->dev, "invalid gain on %pOF\n", - node); - of_node_put(node); + dev_err(dev, "invalid gain on %pfw\n", node); + fwnode_handle_put(node); return -EINVAL; } } - if (!of_property_read_u32(node, "ti,datarate", &pval)) { + if (!fwnode_property_read_u32(node, "ti,datarate", &pval)) { data_rate = pval; if (data_rate > 7) { - dev_err(&client->dev, - "invalid data_rate on %pOF\n", - node); - of_node_put(node); + dev_err(dev, "invalid data_rate on %pfw\n", node); + fwnode_handle_put(node); return -EINVAL; } } data->channel_data[channel].pga = pga; data->channel_data[channel].data_rate = data_rate; + + i++; } - return 0; + return i < 0 ? -EINVAL : 0; } -#endif static void ads1015_get_channels_config(struct i2c_client *client) { @@ -910,10 +904,9 @@ static void ads1015_get_channels_config(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); struct ads1015_data *data = iio_priv(indio_dev); -#ifdef CONFIG_OF - if (!ads1015_get_channels_config_of(client)) + if (!ads1015_client_get_channels_config(client)) return; -#endif + /* fallback on default configuration */ for (k = 0; k < ADS1015_CHANNELS; ++k) { data->channel_data[k].pga = ADS1015_DEFAULT_PGA; @@ -951,9 +944,8 @@ static int ads1015_probe(struct i2c_client *client, indio_dev->name = ADS1015_DRV_NAME; indio_dev->modes = INDIO_DIRECT_MODE; - if (client->dev.of_node) - chip = (enum chip_ids)of_device_get_match_data(&client->dev); - else + chip = (enum chip_ids)device_get_match_data(&client->dev); + if (chip == ADSXXXX) chip = id->driver_data; switch (chip) { case ADS1015: @@ -968,6 +960,9 @@ static int ads1015_probe(struct i2c_client *client, indio_dev->info = &ads1115_info; data->data_rate = (unsigned int *) &ads1115_data_rate; break; + default: + dev_err(&client->dev, "Unknown chip %d\n", chip); + return -EINVAL; } data->event_channel = ADS1015_CHANNELS; From 59c3662b8f081832abaadfbc8a4bfb63c526aea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 9 Dec 2019 21:32:46 +0100 Subject: [PATCH 083/353] iio: adc: ltc2496: provide device tree binding document MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ADC only requires the standard stuff for spi devices and a reference voltage. Signed-off-by: Uwe Kleine-König Signed-off-by: Jonathan Cameron --- .../bindings/iio/adc/lltc,ltc2496.yaml | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml new file mode 100644 index 000000000000..59009997dca0 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/lltc,ltc2496.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Linear Technology / Analog Devices LTC2496 ADC + +maintainers: + - Lars-Peter Clausen + - Michael Hennerich + - Stefan Popa + +properties: + compatible: + enum: + - lltc,ltc2496 + + vref-supply: + description: phandle to an external regulator providing the reference voltage + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle + + reg: + description: spi chipselect number according to the usual spi bindings + + spi-max-frequency: + description: maximal spi bus frequency supported + +required: + - compatible + - vref-supply + - reg + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "lltc,ltc2496"; + reg = <0>; + vref-supply = <<c2496_reg>; + spi-max-frequency = <2000000>; + }; + }; From 69548b7c2c4f1ab9a135f2050d9683c7691ef701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 9 Dec 2019 21:32:47 +0100 Subject: [PATCH 084/353] iio: adc: ltc2497: split protocol independent part in a separate module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows to share most of this driver for the ltc2496 driver added in the next commit that is an SPI variant of the ltc2497. Initially I named the generic part ltc249x, but wild card names are frowned upon, so the generic part is called ltc2497-core even though it's not obvious that this is then to be reused for the ltc2496 driver. Signed-off-by: Uwe Kleine-König Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Makefile | 2 +- drivers/iio/adc/ltc2497-core.c | 243 +++++++++++++++++++++++++++++++++ drivers/iio/adc/ltc2497.c | 234 ++++--------------------------- drivers/iio/adc/ltc2497.h | 18 +++ 4 files changed, 288 insertions(+), 209 deletions(-) create mode 100644 drivers/iio/adc/ltc2497-core.c create mode 100644 drivers/iio/adc/ltc2497.h diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index bf8354cdbc34..5f8d7ac6bbe2 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -51,7 +51,7 @@ obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o obj-$(CONFIG_LTC2471) += ltc2471.o obj-$(CONFIG_LTC2485) += ltc2485.o -obj-$(CONFIG_LTC2497) += ltc2497.o +obj-$(CONFIG_LTC2497) += ltc2497.o ltc2497-core.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX11100) += max11100.o obj-$(CONFIG_MAX1118) += max1118.o diff --git a/drivers/iio/adc/ltc2497-core.c b/drivers/iio/adc/ltc2497-core.c new file mode 100644 index 000000000000..f5f7039caacc --- /dev/null +++ b/drivers/iio/adc/ltc2497-core.c @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ltc2497-core.c - Common code for Analog Devices/Linear Technology + * LTC2496 and LTC2497 ADCs + * + * Copyright (C) 2017 Analog Devices Inc. + */ + +#include +#include +#include +#include +#include + +#include "ltc2497.h" + +#define LTC2497_SGL BIT(4) +#define LTC2497_DIFF 0 +#define LTC2497_SIGN BIT(3) + +static int ltc2497core_wait_conv(struct ltc2497core_driverdata *ddata) +{ + s64 time_elapsed; + + time_elapsed = ktime_ms_delta(ktime_get(), ddata->time_prev); + + if (time_elapsed < LTC2497_CONVERSION_TIME_MS) { + /* delay if conversion time not passed + * since last read or write + */ + if (msleep_interruptible( + LTC2497_CONVERSION_TIME_MS - time_elapsed)) + return -ERESTARTSYS; + + return 0; + } + + if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) { + /* We're in automatic mode - + * so the last reading is still not outdated + */ + return 0; + } + + return 1; +} + +static int ltc2497core_read(struct ltc2497core_driverdata *ddata, u8 address, int *val) +{ + int ret; + + ret = ltc2497core_wait_conv(ddata); + if (ret < 0) + return ret; + + if (ret || ddata->addr_prev != address) { + ret = ddata->result_and_measure(ddata, address, NULL); + if (ret < 0) + return ret; + ddata->addr_prev = address; + + if (msleep_interruptible(LTC2497_CONVERSION_TIME_MS)) + return -ERESTARTSYS; + } + + ret = ddata->result_and_measure(ddata, address, val); + if (ret < 0) + return ret; + + ddata->time_prev = ktime_get(); + + return ret; +} + +static int ltc2497core_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct ltc2497core_driverdata *ddata = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&indio_dev->mlock); + ret = ltc2497core_read(ddata, chan->address, val); + mutex_unlock(&indio_dev->mlock); + if (ret < 0) + return ret; + + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + ret = regulator_get_voltage(ddata->ref); + if (ret < 0) + return ret; + + *val = ret / 1000; + *val2 = 17; + + return IIO_VAL_FRACTIONAL_LOG2; + + default: + return -EINVAL; + } +} + +#define LTC2497_CHAN(_chan, _addr, _ds_name) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (_chan), \ + .address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .datasheet_name = (_ds_name), \ +} + +#define LTC2497_CHAN_DIFF(_chan, _addr) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 1 : 0), \ + .channel2 = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 0 : 1),\ + .address = (_addr | _chan), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .differential = 1, \ +} + +static const struct iio_chan_spec ltc2497core_channel[] = { + LTC2497_CHAN(0, LTC2497_SGL, "CH0"), + LTC2497_CHAN(1, LTC2497_SGL, "CH1"), + LTC2497_CHAN(2, LTC2497_SGL, "CH2"), + LTC2497_CHAN(3, LTC2497_SGL, "CH3"), + LTC2497_CHAN(4, LTC2497_SGL, "CH4"), + LTC2497_CHAN(5, LTC2497_SGL, "CH5"), + LTC2497_CHAN(6, LTC2497_SGL, "CH6"), + LTC2497_CHAN(7, LTC2497_SGL, "CH7"), + LTC2497_CHAN(8, LTC2497_SGL, "CH8"), + LTC2497_CHAN(9, LTC2497_SGL, "CH9"), + LTC2497_CHAN(10, LTC2497_SGL, "CH10"), + LTC2497_CHAN(11, LTC2497_SGL, "CH11"), + LTC2497_CHAN(12, LTC2497_SGL, "CH12"), + LTC2497_CHAN(13, LTC2497_SGL, "CH13"), + LTC2497_CHAN(14, LTC2497_SGL, "CH14"), + LTC2497_CHAN(15, LTC2497_SGL, "CH15"), + LTC2497_CHAN_DIFF(0, LTC2497_DIFF), + LTC2497_CHAN_DIFF(1, LTC2497_DIFF), + LTC2497_CHAN_DIFF(2, LTC2497_DIFF), + LTC2497_CHAN_DIFF(3, LTC2497_DIFF), + LTC2497_CHAN_DIFF(4, LTC2497_DIFF), + LTC2497_CHAN_DIFF(5, LTC2497_DIFF), + LTC2497_CHAN_DIFF(6, LTC2497_DIFF), + LTC2497_CHAN_DIFF(7, LTC2497_DIFF), + LTC2497_CHAN_DIFF(0, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(1, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(2, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(3, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(4, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(5, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(6, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(7, LTC2497_DIFF | LTC2497_SIGN), +}; + +static const struct iio_info ltc2497core_info = { + .read_raw = ltc2497core_read_raw, +}; + +int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev) +{ + struct ltc2497core_driverdata *ddata = iio_priv(indio_dev); + int ret; + + indio_dev->dev.parent = dev; + indio_dev->name = dev_name(dev); + indio_dev->info = <c2497core_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ltc2497core_channel; + indio_dev->num_channels = ARRAY_SIZE(ltc2497core_channel); + + ret = ddata->result_and_measure(ddata, LTC2497_CONFIG_DEFAULT, NULL); + if (ret < 0) + return ret; + + ddata->ref = devm_regulator_get(dev, "vref"); + if (IS_ERR(ddata->ref)) { + if (PTR_ERR(ddata->ref) != -EPROBE_DEFER) + dev_err(dev, "Failed to get vref regulator: %pe\n", + ddata->ref); + + return PTR_ERR(ddata->ref); + } + + ret = regulator_enable(ddata->ref); + if (ret < 0) { + dev_err(dev, "Failed to enable vref regulator: %pe\n", + ERR_PTR(ret)); + return ret; + } + + if (dev->platform_data) { + struct iio_map *plat_data; + + plat_data = (struct iio_map *)dev->platform_data; + + ret = iio_map_array_register(indio_dev, plat_data); + if (ret) { + dev_err(&indio_dev->dev, "iio map err: %d\n", ret); + goto err_regulator_disable; + } + } + + ddata->addr_prev = LTC2497_CONFIG_DEFAULT; + ddata->time_prev = ktime_get(); + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto err_array_unregister; + + return 0; + +err_array_unregister: + iio_map_array_unregister(indio_dev); + +err_regulator_disable: + regulator_disable(ddata->ref); + + return ret; +} +EXPORT_SYMBOL_NS(ltc2497core_probe, LTC2497); + +void ltc2497core_remove(struct iio_dev *indio_dev) +{ + struct ltc2497core_driverdata *ddata = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + iio_map_array_unregister(indio_dev); + + regulator_disable(ddata->ref); +} +EXPORT_SYMBOL_NS(ltc2497core_remove, LTC2497); + +MODULE_DESCRIPTION("common code for LTC2496/LTC2497 drivers"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c index 470406032720..5db63d7c6bc5 100644 --- a/drivers/iio/adc/ltc2497.c +++ b/drivers/iio/adc/ltc2497.c @@ -7,27 +7,18 @@ * Datasheet: http://cds.linear.com/docs/en/datasheet/2497fd.pdf */ -#include #include #include #include -#include #include #include -#include -#define LTC2497_ENABLE 0xA0 -#define LTC2497_SGL BIT(4) -#define LTC2497_DIFF 0 -#define LTC2497_SIGN BIT(3) -#define LTC2497_CONFIG_DEFAULT LTC2497_ENABLE -#define LTC2497_CONVERSION_TIME_MS 150ULL +#include "ltc2497.h" -struct ltc2497_st { +struct ltc2497_driverdata { + /* this must be the first member */ + struct ltc2497core_driverdata common_ddata; struct i2c_client *client; - struct regulator *ref; - ktime_t time_prev; - u8 addr_prev; /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. @@ -35,232 +26,59 @@ struct ltc2497_st { __be32 buf ____cacheline_aligned; }; -static int ltc2497_wait_conv(struct ltc2497_st *st) +static int ltc2497_result_and_measure(struct ltc2497core_driverdata *ddata, + u8 address, int *val) { - s64 time_elapsed; - - time_elapsed = ktime_ms_delta(ktime_get(), st->time_prev); - - if (time_elapsed < LTC2497_CONVERSION_TIME_MS) { - /* delay if conversion time not passed - * since last read or write - */ - if (msleep_interruptible( - LTC2497_CONVERSION_TIME_MS - time_elapsed)) - return -ERESTARTSYS; - - return 0; - } - - if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) { - /* We're in automatic mode - - * so the last reading is stil not outdated - */ - return 0; - } - - return 1; -} - -static int ltc2497_read(struct ltc2497_st *st, u8 address, int *val) -{ - struct i2c_client *client = st->client; + struct ltc2497_driverdata *st = + container_of(ddata, struct ltc2497_driverdata, common_ddata); int ret; - ret = ltc2497_wait_conv(st); - if (ret < 0) - return ret; - - if (ret || st->addr_prev != address) { - ret = i2c_smbus_write_byte(st->client, - LTC2497_ENABLE | address); - if (ret < 0) + if (val) { + ret = i2c_master_recv(st->client, (char *)&st->buf, 3); + if (ret < 0) { + dev_err(&st->client->dev, "i2c_master_recv failed\n"); return ret; - st->addr_prev = address; - if (msleep_interruptible(LTC2497_CONVERSION_TIME_MS)) - return -ERESTARTSYS; - } - ret = i2c_master_recv(client, (char *)&st->buf, 3); - if (ret < 0) { - dev_err(&client->dev, "i2c_master_recv failed\n"); - return ret; - } - st->time_prev = ktime_get(); + } - /* convert and shift the result, - * and finally convert from offset binary to signed integer - */ - *val = (be32_to_cpu(st->buf) >> 14) - (1 << 17); + *val = (be32_to_cpu(st->buf) >> 14) - (1 << 17); + } + ret = i2c_smbus_write_byte(st->client, + LTC2497_ENABLE | address); + if (ret) + dev_err(&st->client->dev, "i2c transfer failed: %pe\n", + ERR_PTR(ret)); return ret; } -static int ltc2497_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, long mask) -{ - struct ltc2497_st *st = iio_priv(indio_dev); - int ret; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - mutex_lock(&indio_dev->mlock); - ret = ltc2497_read(st, chan->address, val); - mutex_unlock(&indio_dev->mlock); - if (ret < 0) - return ret; - - return IIO_VAL_INT; - - case IIO_CHAN_INFO_SCALE: - ret = regulator_get_voltage(st->ref); - if (ret < 0) - return ret; - - *val = ret / 1000; - *val2 = 17; - - return IIO_VAL_FRACTIONAL_LOG2; - - default: - return -EINVAL; - } -} - -#define LTC2497_CHAN(_chan, _addr, _ds_name) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = (_chan), \ - .address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ - .datasheet_name = (_ds_name), \ -} - -#define LTC2497_CHAN_DIFF(_chan, _addr) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 1 : 0), \ - .channel2 = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 0 : 1),\ - .address = (_addr | _chan), \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ - .differential = 1, \ -} - -static const struct iio_chan_spec ltc2497_channel[] = { - LTC2497_CHAN(0, LTC2497_SGL, "CH0"), - LTC2497_CHAN(1, LTC2497_SGL, "CH1"), - LTC2497_CHAN(2, LTC2497_SGL, "CH2"), - LTC2497_CHAN(3, LTC2497_SGL, "CH3"), - LTC2497_CHAN(4, LTC2497_SGL, "CH4"), - LTC2497_CHAN(5, LTC2497_SGL, "CH5"), - LTC2497_CHAN(6, LTC2497_SGL, "CH6"), - LTC2497_CHAN(7, LTC2497_SGL, "CH7"), - LTC2497_CHAN(8, LTC2497_SGL, "CH8"), - LTC2497_CHAN(9, LTC2497_SGL, "CH9"), - LTC2497_CHAN(10, LTC2497_SGL, "CH10"), - LTC2497_CHAN(11, LTC2497_SGL, "CH11"), - LTC2497_CHAN(12, LTC2497_SGL, "CH12"), - LTC2497_CHAN(13, LTC2497_SGL, "CH13"), - LTC2497_CHAN(14, LTC2497_SGL, "CH14"), - LTC2497_CHAN(15, LTC2497_SGL, "CH15"), - LTC2497_CHAN_DIFF(0, LTC2497_DIFF), - LTC2497_CHAN_DIFF(1, LTC2497_DIFF), - LTC2497_CHAN_DIFF(2, LTC2497_DIFF), - LTC2497_CHAN_DIFF(3, LTC2497_DIFF), - LTC2497_CHAN_DIFF(4, LTC2497_DIFF), - LTC2497_CHAN_DIFF(5, LTC2497_DIFF), - LTC2497_CHAN_DIFF(6, LTC2497_DIFF), - LTC2497_CHAN_DIFF(7, LTC2497_DIFF), - LTC2497_CHAN_DIFF(0, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(1, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(2, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(3, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(4, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(5, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(6, LTC2497_DIFF | LTC2497_SIGN), - LTC2497_CHAN_DIFF(7, LTC2497_DIFF | LTC2497_SIGN), -}; - -static const struct iio_info ltc2497_info = { - .read_raw = ltc2497_read_raw, -}; - static int ltc2497_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct iio_dev *indio_dev; - struct ltc2497_st *st; - struct iio_map *plat_data; - int ret; + struct ltc2497_driverdata *st; + struct device *dev = &client->dev; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE)) return -EOPNOTSUPP; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; st = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); st->client = client; + st->common_ddata.result_and_measure = ltc2497_result_and_measure; - indio_dev->dev.parent = &client->dev; - indio_dev->name = id->name; - indio_dev->info = <c2497_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->channels = ltc2497_channel; - indio_dev->num_channels = ARRAY_SIZE(ltc2497_channel); - - st->ref = devm_regulator_get(&client->dev, "vref"); - if (IS_ERR(st->ref)) - return PTR_ERR(st->ref); - - ret = regulator_enable(st->ref); - if (ret < 0) - return ret; - - if (client->dev.platform_data) { - plat_data = ((struct iio_map *)client->dev.platform_data); - ret = iio_map_array_register(indio_dev, plat_data); - if (ret) { - dev_err(&indio_dev->dev, "iio map err: %d\n", ret); - goto err_regulator_disable; - } - } - - ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT); - if (ret < 0) - goto err_array_unregister; - - st->addr_prev = LTC2497_CONFIG_DEFAULT; - st->time_prev = ktime_get(); - - ret = iio_device_register(indio_dev); - if (ret < 0) - goto err_array_unregister; - - return 0; - -err_array_unregister: - iio_map_array_unregister(indio_dev); - -err_regulator_disable: - regulator_disable(st->ref); - - return ret; + return ltc2497core_probe(dev, indio_dev); } static int ltc2497_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct ltc2497_st *st = iio_priv(indio_dev); - iio_map_array_unregister(indio_dev); - iio_device_unregister(indio_dev); - regulator_disable(st->ref); + ltc2497core_remove(indio_dev); return 0; } diff --git a/drivers/iio/adc/ltc2497.h b/drivers/iio/adc/ltc2497.h new file mode 100644 index 000000000000..d0b42dd6b8ad --- /dev/null +++ b/drivers/iio/adc/ltc2497.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#define LTC2497_ENABLE 0xA0 +#define LTC2497_CONFIG_DEFAULT LTC2497_ENABLE +#define LTC2497_CONVERSION_TIME_MS 150ULL + +struct ltc2497core_driverdata { + struct regulator *ref; + ktime_t time_prev; + u8 addr_prev; + int (*result_and_measure)(struct ltc2497core_driverdata *ddata, + u8 address, int *val); +}; + +int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev); +void ltc2497core_remove(struct iio_dev *indio_dev); + +MODULE_IMPORT_NS(LTC2497); From e4c5c4dfaa88e49f33e8c11b52c65c630c0b12a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 9 Dec 2019 21:32:48 +0100 Subject: [PATCH 085/353] iio: adc: new driver to support Linear technology's ltc2496 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This chip is similar to the LTC2497 ADC, it just uses SPI instead of I2C and so has a slightly different protocol. Only the actual hardware access is different. The spi protocol is different enough to not be able to map the differences via a regmap. Also generalize the entry in MAINTAINER to cover the newly introduced file. Signed-off-by: Uwe Kleine-König Signed-off-by: Jonathan Cameron --- MAINTAINERS | 2 +- drivers/iio/adc/Kconfig | 10 ++++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ltc2496.c | 108 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 drivers/iio/adc/ltc2496.c diff --git a/MAINTAINERS b/MAINTAINERS index 01212ae1a2d4..896951d11e50 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1045,7 +1045,7 @@ S: Supported F: Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523 F: Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350 F: drivers/iio/*/ad* -F: drivers/iio/adc/ltc2497* +F: drivers/iio/adc/ltc249* X: drivers/iio/*/adjd* F: drivers/staging/iio/*/ad* diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 27bb4e56eaea..82e33082958c 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -530,6 +530,16 @@ config LTC2485 To compile this driver as a module, choose M here: the module will be called ltc2485. +config LTC2496 + tristate "Linear Technology LTC2496 ADC driver" + depends on SPI + help + Say yes here to build support for Linear Technology LTC2496 + 16-Bit 8-/16-Channel Delta Sigma ADC. + + To compile this driver as a module, choose M here: the module will be + called ltc2496. + config LTC2497 tristate "Linear Technology LTC2497 ADC driver" depends on I2C diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 5f8d7ac6bbe2..919228900df9 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o obj-$(CONFIG_LTC2471) += ltc2471.o obj-$(CONFIG_LTC2485) += ltc2485.o +obj-$(CONFIG_LTC2496) += ltc2496.o ltc2497-core.o obj-$(CONFIG_LTC2497) += ltc2497.o ltc2497-core.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX11100) += max11100.o diff --git a/drivers/iio/adc/ltc2496.c b/drivers/iio/adc/ltc2496.c new file mode 100644 index 000000000000..88a30156a849 --- /dev/null +++ b/drivers/iio/adc/ltc2496.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ltc2496.c - Driver for Analog Devices/Linear Technology LTC2496 ADC + * + * Based on ltc2497.c which has + * Copyright (C) 2017 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/2496fc.pdf + */ + +#include +#include +#include +#include +#include + +#include "ltc2497.h" + +struct ltc2496_driverdata { + /* this must be the first member */ + struct ltc2497core_driverdata common_ddata; + struct spi_device *spi; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + unsigned char rxbuf[3] ____cacheline_aligned; + unsigned char txbuf[3]; +}; + +static int ltc2496_result_and_measure(struct ltc2497core_driverdata *ddata, + u8 address, int *val) +{ + struct ltc2496_driverdata *st = + container_of(ddata, struct ltc2496_driverdata, common_ddata); + struct spi_transfer t = { + .tx_buf = st->txbuf, + .rx_buf = st->rxbuf, + .len = sizeof(st->txbuf), + }; + int ret; + + st->txbuf[0] = LTC2497_ENABLE | address; + + ret = spi_sync_transfer(st->spi, &t, 1); + if (ret < 0) { + dev_err(&st->spi->dev, "spi_sync_transfer failed: %pe\n", + ERR_PTR(ret)); + return ret; + } + + if (val) + *val = ((st->rxbuf[0] & 0x3f) << 12 | + st->rxbuf[1] << 4 | st->rxbuf[2] >> 4) - + (1 << 17); + + return 0; +} + +static int ltc2496_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct ltc2496_driverdata *st; + struct device *dev = &spi->dev; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + st->spi = spi; + st->common_ddata.result_and_measure = ltc2496_result_and_measure; + + return ltc2497core_probe(dev, indio_dev); +} + +static int ltc2496_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + + ltc2497core_remove(indio_dev); + + return 0; +} + +static const struct of_device_id ltc2496_of_match[] = { + { .compatible = "lltc,ltc2496", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ltc2496_of_match); + +static struct spi_driver ltc2496_driver = { + .driver = { + .name = "ltc2496", + .of_match_table = of_match_ptr(ltc2496_of_match), + }, + .probe = ltc2496_probe, + .remove = ltc2496_remove, +}; +module_spi_driver(ltc2496_driver); + +MODULE_AUTHOR("Uwe Kleine-König "); +MODULE_DESCRIPTION("Linear Technology LTC2496 ADC driver"); +MODULE_LICENSE("GPL v2"); From 969fdd86caa5be3e57d9e4b6ba4541ec5a54eae8 Mon Sep 17 00:00:00 2001 From: Rodrigo Carvalho Date: Sat, 7 Dec 2019 01:53:38 -0300 Subject: [PATCH 086/353] staging: iio: accel: adis16240: enforce SPI mode on probe function According to the datasheet, this driver supports only SPI mode 3, so we should enforce it on probe function. Signed-off-by: Rodrigo Carvalho Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16240.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c index a480409090c0..794f063e6c86 100644 --- a/drivers/staging/iio/accel/adis16240.c +++ b/drivers/staging/iio/accel/adis16240.c @@ -399,6 +399,13 @@ static int adis16240_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(adis16240_channels); indio_dev->modes = INDIO_DIRECT_MODE; + spi->mode = SPI_MODE_3; + ret = spi_setup(spi); + if (ret) { + dev_err(&spi->dev, "spi_setup failed!\n"); + return ret; + } + ret = adis_init(st, indio_dev, spi, &adis16240_data); if (ret) return ret; From 5b883564fcdee1aa5ded4354046f03a848aa2370 Mon Sep 17 00:00:00 2001 From: Rodrigo Carvalho Date: Sat, 7 Dec 2019 01:53:39 -0300 Subject: [PATCH 087/353] dt-bindings: iio: accel: add binding documentation for ADIS16240 This patch add device tree binding documentation for ADIS16240. Signed-off-by: Rodrigo Carvalho Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/accel/adi,adis16240.yaml | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/accel/adi,adis16240.yaml diff --git a/Documentation/devicetree/bindings/iio/accel/adi,adis16240.yaml b/Documentation/devicetree/bindings/iio/accel/adi,adis16240.yaml new file mode 100644 index 000000000000..4147f02b5e3c --- /dev/null +++ b/Documentation/devicetree/bindings/iio/accel/adi,adis16240.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/accel/adi,adis16240.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ADIS16240 Programmable Impact Sensor and Recorder driver + +maintainers: + - Alexandru Ardelean + +description: | + ADIS16240 Programmable Impact Sensor and Recorder driver that supports + SPI interface. + https://www.analog.com/en/products/adis16240.html + +properties: + compatible: + enum: + - adi,adis16240 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +examples: + - | + #include + #include + spi0 { + #address-cells = <1>; + #size-cells = <0>; + + /* Example for a SPI device node */ + accelerometer@0 { + compatible = "adi,adis16240"; + reg = <0>; + spi-max-frequency = <2500000>; + interrupt-parent = <&gpio0>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + }; + }; From b33bdf8020c94438269becc6dace9ed49257c4ba Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 16 Dec 2019 20:48:56 +0100 Subject: [PATCH 088/353] isdn: don't mark kcapi_proc_exit as __exit As everybody pointed out by now, my patch to clean up CAPI introduced a link time warning, as the two parts of the capi driver are now in one module and the exit function may need to be called in the error path of the init function: >> WARNING: drivers/isdn/capi/kernelcapi.o(.text+0xea4): Section mismatch in reference from the function kcapi_exit() to the function .exit.text:kcapi_proc_exit() The function kcapi_exit() references a function in an exit section. Often the function kcapi_proc_exit() has valid usage outside the exit section and the fix is to remove the __exit annotation of kcapi_proc_exit. Remove the incorrect __exit annotation. Reported-by: kbuild test robot Reported-by: kernelci.org bot Reported-by: Olof's autobuilder Reported-by: Stephen Rothwell Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20191216194909.1983639-1-arnd@arndb.de Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/capi/kcapi_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index 2bffbb8bf271..eadbe59b3753 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -217,7 +217,7 @@ kcapi_proc_init(void) proc_create("capi/driver", 0, NULL, &empty_fops); } -void __exit +void kcapi_proc_exit(void) { remove_proc_entry("capi/driver", NULL); From 710d7fbe21ee2ceab121f1f84a20edf68f9f9742 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 10 Dec 2019 10:15:08 +0100 Subject: [PATCH 089/353] staging: octeon: delete driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver has been in the tree since 2009 with no real movement to get it out. Now it is starting to cause build issues and other problems for people who want to fix coding style problems, but can not actually build it. As nothing is happening here, just delete the module entirely. Reported-by: Guenter Roeck Acked-by: Guenter Roeck Cc: David Daney Cc: "David S. Miller" Cc: "Matthew Wilcox (Oracle)" Cc: Guenter Roeck Cc: YueHaibing Cc: Aaro Koskinen Cc: Wambui Karuga Cc: Julia Lawall Cc: Florian Westphal Cc: Geert Uytterhoeven Cc: Branden Bonaby Cc: "Petr Å tetiar" Cc: Sandro Volery Cc: Paul Burton Cc: Dan Carpenter Cc: Giovanni Gherdovich Cc: Valery Ivanov Link: https://lore.kernel.org/r/20191210091509.3546251-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/octeon/Kconfig | 16 - drivers/staging/octeon/Makefile | 19 - drivers/staging/octeon/TODO | 9 - drivers/staging/octeon/ethernet-defines.h | 40 - drivers/staging/octeon/ethernet-mdio.c | 178 --- drivers/staging/octeon/ethernet-mdio.h | 28 - drivers/staging/octeon/ethernet-mem.c | 154 --- drivers/staging/octeon/ethernet-mem.h | 9 - drivers/staging/octeon/ethernet-rgmii.c | 158 --- drivers/staging/octeon/ethernet-rx.c | 538 -------- drivers/staging/octeon/ethernet-rx.h | 31 - drivers/staging/octeon/ethernet-sgmii.c | 30 - drivers/staging/octeon/ethernet-spi.c | 226 ---- drivers/staging/octeon/ethernet-tx.c | 717 ----------- drivers/staging/octeon/ethernet-tx.h | 14 - drivers/staging/octeon/ethernet-util.h | 47 - drivers/staging/octeon/ethernet.c | 992 -------------- drivers/staging/octeon/octeon-ethernet.h | 107 -- drivers/staging/octeon/octeon-stubs.h | 1433 --------------------- 21 files changed, 4749 deletions(-) delete mode 100644 drivers/staging/octeon/Kconfig delete mode 100644 drivers/staging/octeon/Makefile delete mode 100644 drivers/staging/octeon/TODO delete mode 100644 drivers/staging/octeon/ethernet-defines.h delete mode 100644 drivers/staging/octeon/ethernet-mdio.c delete mode 100644 drivers/staging/octeon/ethernet-mdio.h delete mode 100644 drivers/staging/octeon/ethernet-mem.c delete mode 100644 drivers/staging/octeon/ethernet-mem.h delete mode 100644 drivers/staging/octeon/ethernet-rgmii.c delete mode 100644 drivers/staging/octeon/ethernet-rx.c delete mode 100644 drivers/staging/octeon/ethernet-rx.h delete mode 100644 drivers/staging/octeon/ethernet-sgmii.c delete mode 100644 drivers/staging/octeon/ethernet-spi.c delete mode 100644 drivers/staging/octeon/ethernet-tx.c delete mode 100644 drivers/staging/octeon/ethernet-tx.h delete mode 100644 drivers/staging/octeon/ethernet-util.h delete mode 100644 drivers/staging/octeon/ethernet.c delete mode 100644 drivers/staging/octeon/octeon-ethernet.h delete mode 100644 drivers/staging/octeon/octeon-stubs.h diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 3a334a9dd453..f1926e8abc80 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -42,8 +42,6 @@ source "drivers/staging/rtl8188eu/Kconfig" source "drivers/staging/rts5208/Kconfig" -source "drivers/staging/octeon/Kconfig" - source "drivers/staging/octeon-usb/Kconfig" source "drivers/staging/vt6655/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index fb0c518ce07c..d5411677a45f 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -12,7 +12,6 @@ obj-$(CONFIG_R8712U) += rtl8712/ obj-$(CONFIG_R8188EU) += rtl8188eu/ obj-$(CONFIG_RTS5208) += rts5208/ obj-$(CONFIG_NETLOGIC_XLR_NET) += netlogic/ -obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ obj-$(CONFIG_OCTEON_USB) += octeon-usb/ obj-$(CONFIG_VT6655) += vt6655/ obj-$(CONFIG_VT6656) += vt6656/ diff --git a/drivers/staging/octeon/Kconfig b/drivers/staging/octeon/Kconfig deleted file mode 100644 index e7f4ddcc1361..000000000000 --- a/drivers/staging/octeon/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config OCTEON_ETHERNET - tristate "Cavium Networks Octeon Ethernet support" - depends on CAVIUM_OCTEON_SOC || COMPILE_TEST - depends on NETDEVICES - depends on BROKEN - select PHYLIB - select MDIO_OCTEON - help - This driver supports the builtin ethernet ports on Cavium - Networks' products in the Octeon family. This driver supports the - CN3XXX and CN5XXX Octeon processors. - - To compile this driver as a module, choose M here. The module - will be called octeon-ethernet. - diff --git a/drivers/staging/octeon/Makefile b/drivers/staging/octeon/Makefile deleted file mode 100644 index 3887cf5f1e84..000000000000 --- a/drivers/staging/octeon/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Copyright (C) 2005-2009 Cavium Networks -# - -# -# Makefile for Cavium OCTEON on-board ethernet driver -# - -obj-${CONFIG_OCTEON_ETHERNET} := octeon-ethernet.o - -octeon-ethernet-y := ethernet.o -octeon-ethernet-y += ethernet-mdio.o -octeon-ethernet-y += ethernet-mem.o -octeon-ethernet-y += ethernet-rgmii.o -octeon-ethernet-y += ethernet-rx.o -octeon-ethernet-y += ethernet-sgmii.o -octeon-ethernet-y += ethernet-spi.o -octeon-ethernet-y += ethernet-tx.o diff --git a/drivers/staging/octeon/TODO b/drivers/staging/octeon/TODO deleted file mode 100644 index 67a0a1f6b922..000000000000 --- a/drivers/staging/octeon/TODO +++ /dev/null @@ -1,9 +0,0 @@ -This driver is functional and supports Ethernet on OCTEON+/OCTEON2/OCTEON3 -chips at least up to CN7030. - -TODO: - - general code review and clean up - - make driver self-contained instead of being split between staging and - arch/mips/cavium-octeon. - -Contact: Aaro Koskinen diff --git a/drivers/staging/octeon/ethernet-defines.h b/drivers/staging/octeon/ethernet-defines.h deleted file mode 100644 index ef9e767b0e2e..000000000000 --- a/drivers/staging/octeon/ethernet-defines.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2007 Cavium Networks - */ - -/* - * A few defines are used to control the operation of this driver: - * USE_ASYNC_IOBDMA - * Use asynchronous IO access to hardware. This uses Octeon's asynchronous - * IOBDMAs to issue IO accesses without stalling. Set this to zero - * to disable this. Note that IOBDMAs require CVMSEG. - * REUSE_SKBUFFS_WITHOUT_FREE - * Allows the TX path to free an skbuff into the FPA hardware pool. This - * can significantly improve performance for forwarding and bridging, but - * may be somewhat dangerous. Checks are made, but if any buffer is reused - * without the proper Linux cleanup, the networking stack may have very - * bizarre bugs. - */ -#ifndef __ETHERNET_DEFINES_H__ -#define __ETHERNET_DEFINES_H__ - -#ifdef CONFIG_NETFILTER -#define REUSE_SKBUFFS_WITHOUT_FREE 0 -#else -#define REUSE_SKBUFFS_WITHOUT_FREE 1 -#endif - -#define USE_ASYNC_IOBDMA (CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0) - -/* Maximum number of SKBs to try to free per xmit packet. */ -#define MAX_OUT_QUEUE_DEPTH 1000 - -#define FAU_TOTAL_TX_TO_CLEAN (CVMX_FAU_REG_END - sizeof(u32)) -#define FAU_NUM_PACKET_BUFFERS_TO_FREE (FAU_TOTAL_TX_TO_CLEAN - sizeof(u32)) - -#define TOTAL_NUMBER_OF_PORTS (CVMX_PIP_NUM_INPUT_PORTS + 1) - -#endif /* __ETHERNET_DEFINES_H__ */ diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c deleted file mode 100644 index c798672d61b2..000000000000 --- a/drivers/staging/octeon/ethernet-mdio.c +++ /dev/null @@ -1,178 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2007 Cavium Networks - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "octeon-ethernet.h" -#include "ethernet-defines.h" -#include "ethernet-mdio.h" -#include "ethernet-util.h" - -static void cvm_oct_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); - strlcpy(info->version, UTS_RELEASE, sizeof(info->version)); - strlcpy(info->bus_info, "Builtin", sizeof(info->bus_info)); -} - -static int cvm_oct_nway_reset(struct net_device *dev) -{ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (dev->phydev) - return phy_start_aneg(dev->phydev); - - return -EINVAL; -} - -const struct ethtool_ops cvm_oct_ethtool_ops = { - .get_drvinfo = cvm_oct_get_drvinfo, - .nway_reset = cvm_oct_nway_reset, - .get_link = ethtool_op_get_link, - .get_link_ksettings = phy_ethtool_get_link_ksettings, - .set_link_ksettings = phy_ethtool_set_link_ksettings, -}; - -/** - * cvm_oct_ioctl - IOCTL support for PHY control - * @dev: Device to change - * @rq: the request - * @cmd: the command - * - * Returns Zero on success - */ -int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - if (!netif_running(dev)) - return -EINVAL; - - if (!dev->phydev) - return -EINVAL; - - return phy_mii_ioctl(dev->phydev, rq, cmd); -} - -void cvm_oct_note_carrier(struct octeon_ethernet *priv, - union cvmx_helper_link_info li) -{ - if (li.s.link_up) { - pr_notice_ratelimited("%s: %u Mbps %s duplex, port %d, queue %d\n", - netdev_name(priv->netdev), li.s.speed, - (li.s.full_duplex) ? "Full" : "Half", - priv->port, priv->queue); - } else { - pr_notice_ratelimited("%s: Link down\n", - netdev_name(priv->netdev)); - } -} - -void cvm_oct_adjust_link(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - union cvmx_helper_link_info link_info; - - link_info.u64 = 0; - link_info.s.link_up = dev->phydev->link ? 1 : 0; - link_info.s.full_duplex = dev->phydev->duplex ? 1 : 0; - link_info.s.speed = dev->phydev->speed; - priv->link_info = link_info.u64; - - /* - * The polling task need to know about link status changes. - */ - if (priv->poll) - priv->poll(dev); - - if (priv->last_link != dev->phydev->link) { - priv->last_link = dev->phydev->link; - cvmx_helper_link_set(priv->port, link_info); - cvm_oct_note_carrier(priv, link_info); - } -} - -int cvm_oct_common_stop(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - int interface = INTERFACE(priv->port); - union cvmx_helper_link_info link_info; - union cvmx_gmxx_prtx_cfg gmx_cfg; - int index = INDEX(priv->port); - - gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); - gmx_cfg.s.en = 0; - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); - - priv->poll = NULL; - - if (dev->phydev) - phy_disconnect(dev->phydev); - - if (priv->last_link) { - link_info.u64 = 0; - priv->last_link = 0; - - cvmx_helper_link_set(priv->port, link_info); - cvm_oct_note_carrier(priv, link_info); - } - return 0; -} - -/** - * cvm_oct_phy_setup_device - setup the PHY - * - * @dev: Device to setup - * - * Returns Zero on success, negative on failure - */ -int cvm_oct_phy_setup_device(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - struct device_node *phy_node; - struct phy_device *phydev = NULL; - - if (!priv->of_node) - goto no_phy; - - phy_node = of_parse_phandle(priv->of_node, "phy-handle", 0); - if (!phy_node && of_phy_is_fixed_link(priv->of_node)) { - int rc; - - rc = of_phy_register_fixed_link(priv->of_node); - if (rc) - return rc; - - phy_node = of_node_get(priv->of_node); - } - if (!phy_node) - goto no_phy; - - phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0, - priv->phy_mode); - of_node_put(phy_node); - - if (!phydev) - return -ENODEV; - - priv->last_link = 0; - phy_start(phydev); - - return 0; -no_phy: - /* If there is no phy, assume a direct MAC connection and that - * the link is up. - */ - netif_carrier_on(dev); - return 0; -} diff --git a/drivers/staging/octeon/ethernet-mdio.h b/drivers/staging/octeon/ethernet-mdio.h deleted file mode 100644 index e3771d48c49b..000000000000 --- a/drivers/staging/octeon/ethernet-mdio.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2007 Cavium Networks - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_XFRM -#include -#include -#endif /* CONFIG_XFRM */ - -extern const struct ethtool_ops cvm_oct_ethtool_ops; - -void octeon_mdiobus_force_mod_depencency(void); - -int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -int cvm_oct_phy_setup_device(struct net_device *dev); diff --git a/drivers/staging/octeon/ethernet-mem.c b/drivers/staging/octeon/ethernet-mem.c deleted file mode 100644 index 532594957ebc..000000000000 --- a/drivers/staging/octeon/ethernet-mem.c +++ /dev/null @@ -1,154 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2010 Cavium Networks - */ - -#include -#include -#include - -#include "octeon-ethernet.h" -#include "ethernet-mem.h" -#include "ethernet-defines.h" - -/** - * cvm_oct_fill_hw_skbuff - fill the supplied hardware pool with skbuffs - * @pool: Pool to allocate an skbuff for - * @size: Size of the buffer needed for the pool - * @elements: Number of buffers to allocate - * - * Returns the actual number of buffers allocated. - */ -static int cvm_oct_fill_hw_skbuff(int pool, int size, int elements) -{ - int freed = elements; - - while (freed) { - struct sk_buff *skb = dev_alloc_skb(size + 256); - - if (unlikely(!skb)) - break; - skb_reserve(skb, 256 - (((unsigned long)skb->data) & 0x7f)); - *(struct sk_buff **)(skb->data - sizeof(void *)) = skb; - cvmx_fpa_free(skb->data, pool, size / 128); - freed--; - } - return elements - freed; -} - -/** - * cvm_oct_free_hw_skbuff- free hardware pool skbuffs - * @pool: Pool to allocate an skbuff for - * @size: Size of the buffer needed for the pool - * @elements: Number of buffers to allocate - */ -static void cvm_oct_free_hw_skbuff(int pool, int size, int elements) -{ - char *memory; - - do { - memory = cvmx_fpa_alloc(pool); - if (memory) { - struct sk_buff *skb = - *(struct sk_buff **)(memory - sizeof(void *)); - elements--; - dev_kfree_skb(skb); - } - } while (memory); - - if (elements < 0) - pr_warn("Freeing of pool %u had too many skbuffs (%d)\n", - pool, elements); - else if (elements > 0) - pr_warn("Freeing of pool %u is missing %d skbuffs\n", - pool, elements); -} - -/** - * cvm_oct_fill_hw_memory - fill a hardware pool with memory. - * @pool: Pool to populate - * @size: Size of each buffer in the pool - * @elements: Number of buffers to allocate - * - * Returns the actual number of buffers allocated. - */ -static int cvm_oct_fill_hw_memory(int pool, int size, int elements) -{ - char *memory; - char *fpa; - int freed = elements; - - while (freed) { - /* - * FPA memory must be 128 byte aligned. Since we are - * aligning we need to save the original pointer so we - * can feed it to kfree when the memory is returned to - * the kernel. - * - * We allocate an extra 256 bytes to allow for - * alignment and space for the original pointer saved - * just before the block. - */ - memory = kmalloc(size + 256, GFP_ATOMIC); - if (unlikely(!memory)) { - pr_warn("Unable to allocate %u bytes for FPA pool %d\n", - elements * size, pool); - break; - } - fpa = (char *)(((unsigned long)memory + 256) & ~0x7fUL); - *((char **)fpa - 1) = memory; - cvmx_fpa_free(fpa, pool, 0); - freed--; - } - return elements - freed; -} - -/** - * cvm_oct_free_hw_memory - Free memory allocated by cvm_oct_fill_hw_memory - * @pool: FPA pool to free - * @size: Size of each buffer in the pool - * @elements: Number of buffers that should be in the pool - */ -static void cvm_oct_free_hw_memory(int pool, int size, int elements) -{ - char *memory; - char *fpa; - - do { - fpa = cvmx_fpa_alloc(pool); - if (fpa) { - elements--; - fpa = (char *)phys_to_virt(cvmx_ptr_to_phys(fpa)); - memory = *((char **)fpa - 1); - kfree(memory); - } - } while (fpa); - - if (elements < 0) - pr_warn("Freeing of pool %u had too many buffers (%d)\n", - pool, elements); - else if (elements > 0) - pr_warn("Warning: Freeing of pool %u is missing %d buffers\n", - pool, elements); -} - -int cvm_oct_mem_fill_fpa(int pool, int size, int elements) -{ - int freed; - - if (pool == CVMX_FPA_PACKET_POOL) - freed = cvm_oct_fill_hw_skbuff(pool, size, elements); - else - freed = cvm_oct_fill_hw_memory(pool, size, elements); - return freed; -} - -void cvm_oct_mem_empty_fpa(int pool, int size, int elements) -{ - if (pool == CVMX_FPA_PACKET_POOL) - cvm_oct_free_hw_skbuff(pool, size, elements); - else - cvm_oct_free_hw_memory(pool, size, elements); -} diff --git a/drivers/staging/octeon/ethernet-mem.h b/drivers/staging/octeon/ethernet-mem.h deleted file mode 100644 index 692dcdb7154d..000000000000 --- a/drivers/staging/octeon/ethernet-mem.h +++ /dev/null @@ -1,9 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2007 Cavium Networks - */ - -int cvm_oct_mem_fill_fpa(int pool, int size, int elements); -void cvm_oct_mem_empty_fpa(int pool, int size, int elements); diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c deleted file mode 100644 index 0c4fac31540a..000000000000 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ /dev/null @@ -1,158 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2007 Cavium Networks - */ - -#include -#include -#include -#include -#include -#include - -#include "octeon-ethernet.h" -#include "ethernet-defines.h" -#include "ethernet-util.h" -#include "ethernet-mdio.h" - -static DEFINE_SPINLOCK(global_register_lock); - -static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable) -{ - union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; - union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs; - union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - - /* Set preamble checking. */ - gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, - interface)); - gmxx_rxx_frm_ctl.s.pre_chk = enable; - cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface), - gmxx_rxx_frm_ctl.u64); - - /* Set FCS stripping. */ - ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS); - if (enable) - ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port; - else - ipd_sub_port_fcs.s.port_bit &= - 0xffffffffull ^ (1ull << priv->port); - cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64); - - /* Clear any error bits. */ - gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, - interface)); - cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), - gmxx_rxx_int_reg.u64); -} - -static void cvm_oct_check_preamble_errors(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - union cvmx_helper_link_info link_info; - unsigned long flags; - - link_info.u64 = priv->link_info; - - /* - * Take the global register lock since we are going to - * touch registers that affect more than one port. - */ - spin_lock_irqsave(&global_register_lock, flags); - - if (link_info.s.speed == 10 && priv->last_speed == 10) { - /* - * Read the GMXX_RXX_INT_REG[PCTERR] bit and see if we are - * getting preamble errors. - */ - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; - - gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG - (index, interface)); - if (gmxx_rxx_int_reg.s.pcterr) { - /* - * We are getting preamble errors at 10Mbps. Most - * likely the PHY is giving us packets with misaligned - * preambles. In order to get these packets we need to - * disable preamble checking and do it in software. - */ - cvm_oct_set_hw_preamble(priv, false); - printk_ratelimited("%s: Using 10Mbps with software preamble removal\n", - dev->name); - } - } else { - /* - * Since the 10Mbps preamble workaround is allowed we need to - * enable preamble checking, FCS stripping, and clear error - * bits on every speed change. If errors occur during 10Mbps - * operation the above code will change this stuff - */ - if (priv->last_speed != link_info.s.speed) - cvm_oct_set_hw_preamble(priv, true); - priv->last_speed = link_info.s.speed; - } - spin_unlock_irqrestore(&global_register_lock, flags); -} - -static void cvm_oct_rgmii_poll(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - union cvmx_helper_link_info link_info; - bool status_change; - - link_info = cvmx_helper_link_get(priv->port); - if (priv->link_info != link_info.u64 && - cvmx_helper_link_set(priv->port, link_info)) - link_info.u64 = priv->link_info; - status_change = priv->link_info != link_info.u64; - priv->link_info = link_info.u64; - - cvm_oct_check_preamble_errors(dev); - - if (likely(!status_change)) - return; - - /* Tell core. */ - if (link_info.s.link_up) { - if (!netif_carrier_ok(dev)) - netif_carrier_on(dev); - } else if (netif_carrier_ok(dev)) { - netif_carrier_off(dev); - } - cvm_oct_note_carrier(priv, link_info); -} - -int cvm_oct_rgmii_open(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - int ret; - - ret = cvm_oct_common_open(dev, cvm_oct_rgmii_poll); - if (ret) - return ret; - - if (dev->phydev) { - /* - * In phydev mode, we need still periodic polling for the - * preamble error checking, and we also need to call this - * function on every link state change. - * - * Only true RGMII ports need to be polled. In GMII mode, port - * 0 is really a RGMII port. - */ - if ((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII && - priv->port == 0) || - (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { - priv->poll = cvm_oct_check_preamble_errors; - cvm_oct_check_preamble_errors(dev); - } - } - - return 0; -} diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c deleted file mode 100644 index 2c16230f993c..000000000000 --- a/drivers/staging/octeon/ethernet-rx.c +++ /dev/null @@ -1,538 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2010 Cavium Networks - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_XFRM -#include -#include -#endif /* CONFIG_XFRM */ - -#include "octeon-ethernet.h" -#include "ethernet-defines.h" -#include "ethernet-mem.h" -#include "ethernet-rx.h" -#include "ethernet-util.h" - -static atomic_t oct_rx_ready = ATOMIC_INIT(0); - -static struct oct_rx_group { - int irq; - int group; - struct napi_struct napi; -} oct_rx_group[16]; - -/** - * cvm_oct_do_interrupt - interrupt handler. - * @irq: Interrupt number. - * @napi_id: Cookie to identify the NAPI instance. - * - * The interrupt occurs whenever the POW has packets in our group. - * - */ -static irqreturn_t cvm_oct_do_interrupt(int irq, void *napi_id) -{ - /* Disable the IRQ and start napi_poll. */ - disable_irq_nosync(irq); - napi_schedule(napi_id); - - return IRQ_HANDLED; -} - -/** - * cvm_oct_check_rcv_error - process receive errors - * @work: Work queue entry pointing to the packet. - * - * Returns Non-zero if the packet can be dropped, zero otherwise. - */ -static inline int cvm_oct_check_rcv_error(struct cvmx_wqe *work) -{ - int port; - - if (octeon_has_feature(OCTEON_FEATURE_PKND)) - port = work->word0.pip.cn68xx.pknd; - else - port = work->word1.cn38xx.ipprt; - - if ((work->word2.snoip.err_code == 10) && (work->word1.len <= 64)) { - /* - * Ignore length errors on min size packets. Some - * equipment incorrectly pads packets to 64+4FCS - * instead of 60+4FCS. Note these packets still get - * counted as frame errors. - */ - } else if (work->word2.snoip.err_code == 5 || - work->word2.snoip.err_code == 7) { - /* - * We received a packet with either an alignment error - * or a FCS error. This may be signalling that we are - * running 10Mbps with GMXX_RXX_FRM_CTL[PRE_CHK] - * off. If this is the case we need to parse the - * packet to determine if we can remove a non spec - * preamble and generate a correct packet. - */ - int interface = cvmx_helper_get_interface_num(port); - int index = cvmx_helper_get_interface_index_num(port); - union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; - - gmxx_rxx_frm_ctl.u64 = - cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface)); - if (gmxx_rxx_frm_ctl.s.pre_chk == 0) { - u8 *ptr = - cvmx_phys_to_ptr(work->packet_ptr.s.addr); - int i = 0; - - while (i < work->word1.len - 1) { - if (*ptr != 0x55) - break; - ptr++; - i++; - } - - if (*ptr == 0xd5) { - /* Port received 0xd5 preamble */ - work->packet_ptr.s.addr += i + 1; - work->word1.len -= i + 5; - } else if ((*ptr & 0xf) == 0xd) { - /* Port received 0xd preamble */ - work->packet_ptr.s.addr += i; - work->word1.len -= i + 4; - for (i = 0; i < work->word1.len; i++) { - *ptr = - ((*ptr & 0xf0) >> 4) | - ((*(ptr + 1) & 0xf) << 4); - ptr++; - } - } else { - printk_ratelimited("Port %d unknown preamble, packet dropped\n", - port); - cvm_oct_free_work(work); - return 1; - } - } - } else { - printk_ratelimited("Port %d receive error code %d, packet dropped\n", - port, work->word2.snoip.err_code); - cvm_oct_free_work(work); - return 1; - } - - return 0; -} - -static void copy_segments_to_skb(struct cvmx_wqe *work, struct sk_buff *skb) -{ - int segments = work->word2.s.bufs; - union cvmx_buf_ptr segment_ptr = work->packet_ptr; - int len = work->word1.len; - int segment_size; - - while (segments--) { - union cvmx_buf_ptr next_ptr; - - next_ptr = *(union cvmx_buf_ptr *) - cvmx_phys_to_ptr(segment_ptr.s.addr - 8); - - /* - * Octeon Errata PKI-100: The segment size is wrong. - * - * Until it is fixed, calculate the segment size based on - * the packet pool buffer size. - * When it is fixed, the following line should be replaced - * with this one: - * int segment_size = segment_ptr.s.size; - */ - segment_size = - CVMX_FPA_PACKET_POOL_SIZE - - (segment_ptr.s.addr - - (((segment_ptr.s.addr >> 7) - - segment_ptr.s.back) << 7)); - - /* Don't copy more than what is left in the packet */ - if (segment_size > len) - segment_size = len; - - /* Copy the data into the packet */ - skb_put_data(skb, cvmx_phys_to_ptr(segment_ptr.s.addr), - segment_size); - len -= segment_size; - segment_ptr = next_ptr; - } -} - -static int cvm_oct_poll(struct oct_rx_group *rx_group, int budget) -{ - const int coreid = cvmx_get_core_num(); - u64 old_group_mask; - u64 old_scratch; - int rx_count = 0; - int did_work_request = 0; - int packet_not_copied; - - /* Prefetch cvm_oct_device since we know we need it soon */ - prefetch(cvm_oct_device); - - if (USE_ASYNC_IOBDMA) { - /* Save scratch in case userspace is using it */ - CVMX_SYNCIOBDMA; - old_scratch = cvmx_scratch_read64(CVMX_SCR_SCRATCH); - } - - /* Only allow work for our group (and preserve priorities) */ - if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { - old_group_mask = cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid)); - cvmx_write_csr(CVMX_SSO_PPX_GRP_MSK(coreid), - BIT(rx_group->group)); - cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid)); /* Flush */ - } else { - old_group_mask = cvmx_read_csr(CVMX_POW_PP_GRP_MSKX(coreid)); - cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), - (old_group_mask & ~0xFFFFull) | - BIT(rx_group->group)); - } - - if (USE_ASYNC_IOBDMA) { - cvmx_pow_work_request_async(CVMX_SCR_SCRATCH, CVMX_POW_NO_WAIT); - did_work_request = 1; - } - - while (rx_count < budget) { - struct sk_buff *skb = NULL; - struct sk_buff **pskb = NULL; - int skb_in_hw; - struct cvmx_wqe *work; - int port; - - if (USE_ASYNC_IOBDMA && did_work_request) - work = cvmx_pow_work_response_async(CVMX_SCR_SCRATCH); - else - work = cvmx_pow_work_request_sync(CVMX_POW_NO_WAIT); - - prefetch(work); - did_work_request = 0; - if (!work) { - if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { - cvmx_write_csr(CVMX_SSO_WQ_IQ_DIS, - BIT(rx_group->group)); - cvmx_write_csr(CVMX_SSO_WQ_INT, - BIT(rx_group->group)); - } else { - union cvmx_pow_wq_int wq_int; - - wq_int.u64 = 0; - wq_int.s.iq_dis = BIT(rx_group->group); - wq_int.s.wq_int = BIT(rx_group->group); - cvmx_write_csr(CVMX_POW_WQ_INT, wq_int.u64); - } - break; - } - pskb = (struct sk_buff **) - (cvm_oct_get_buffer_ptr(work->packet_ptr) - - sizeof(void *)); - prefetch(pskb); - - if (USE_ASYNC_IOBDMA && rx_count < (budget - 1)) { - cvmx_pow_work_request_async_nocheck(CVMX_SCR_SCRATCH, - CVMX_POW_NO_WAIT); - did_work_request = 1; - } - rx_count++; - - skb_in_hw = work->word2.s.bufs == 1; - if (likely(skb_in_hw)) { - skb = *pskb; - prefetch(&skb->head); - prefetch(&skb->len); - } - - if (octeon_has_feature(OCTEON_FEATURE_PKND)) - port = work->word0.pip.cn68xx.pknd; - else - port = work->word1.cn38xx.ipprt; - - prefetch(cvm_oct_device[port]); - - /* Immediately throw away all packets with receive errors */ - if (unlikely(work->word2.snoip.rcv_error)) { - if (cvm_oct_check_rcv_error(work)) - continue; - } - - /* - * We can only use the zero copy path if skbuffs are - * in the FPA pool and the packet fits in a single - * buffer. - */ - if (likely(skb_in_hw)) { - skb->data = skb->head + work->packet_ptr.s.addr - - cvmx_ptr_to_phys(skb->head); - prefetch(skb->data); - skb->len = work->word1.len; - skb_set_tail_pointer(skb, skb->len); - packet_not_copied = 1; - } else { - /* - * We have to copy the packet. First allocate - * an skbuff for it. - */ - skb = dev_alloc_skb(work->word1.len); - if (!skb) { - cvm_oct_free_work(work); - continue; - } - - /* - * Check if we've received a packet that was - * entirely stored in the work entry. - */ - if (unlikely(work->word2.s.bufs == 0)) { - u8 *ptr = work->packet_data; - - if (likely(!work->word2.s.not_IP)) { - /* - * The beginning of the packet - * moves for IP packets. - */ - if (work->word2.s.is_v6) - ptr += 2; - else - ptr += 6; - } - skb_put_data(skb, ptr, work->word1.len); - /* No packet buffers to free */ - } else { - copy_segments_to_skb(work, skb); - } - packet_not_copied = 0; - } - if (likely((port < TOTAL_NUMBER_OF_PORTS) && - cvm_oct_device[port])) { - struct net_device *dev = cvm_oct_device[port]; - - /* - * Only accept packets for devices that are - * currently up. - */ - if (likely(dev->flags & IFF_UP)) { - skb->protocol = eth_type_trans(skb, dev); - skb->dev = dev; - - if (unlikely(work->word2.s.not_IP || - work->word2.s.IP_exc || - work->word2.s.L4_error || - !work->word2.s.tcp_or_udp)) - skb->ip_summed = CHECKSUM_NONE; - else - skb->ip_summed = CHECKSUM_UNNECESSARY; - - /* Increment RX stats for virtual ports */ - if (port >= CVMX_PIP_NUM_INPUT_PORTS) { - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; - } - netif_receive_skb(skb); - } else { - /* - * Drop any packet received for a device that - * isn't up. - */ - dev->stats.rx_dropped++; - dev_kfree_skb_irq(skb); - } - } else { - /* - * Drop any packet received for a device that - * doesn't exist. - */ - printk_ratelimited("Port %d not controlled by Linux, packet dropped\n", - port); - dev_kfree_skb_irq(skb); - } - /* - * Check to see if the skbuff and work share the same - * packet buffer. - */ - if (likely(packet_not_copied)) { - /* - * This buffer needs to be replaced, increment - * the number of buffers we need to free by - * one. - */ - cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, - 1); - - cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 1); - } else { - cvm_oct_free_work(work); - } - } - /* Restore the original POW group mask */ - if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { - cvmx_write_csr(CVMX_SSO_PPX_GRP_MSK(coreid), old_group_mask); - cvmx_read_csr(CVMX_SSO_PPX_GRP_MSK(coreid)); /* Flush */ - } else { - cvmx_write_csr(CVMX_POW_PP_GRP_MSKX(coreid), old_group_mask); - } - - if (USE_ASYNC_IOBDMA) { - /* Restore the scratch area */ - cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch); - } - cvm_oct_rx_refill_pool(0); - - return rx_count; -} - -/** - * cvm_oct_napi_poll - the NAPI poll function. - * @napi: The NAPI instance. - * @budget: Maximum number of packets to receive. - * - * Returns the number of packets processed. - */ -static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) -{ - struct oct_rx_group *rx_group = container_of(napi, struct oct_rx_group, - napi); - int rx_count; - - rx_count = cvm_oct_poll(rx_group, budget); - - if (rx_count < budget) { - /* No more work */ - napi_complete_done(napi, rx_count); - enable_irq(rx_group->irq); - } - return rx_count; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/** - * cvm_oct_poll_controller - poll for receive packets - * device. - * - * @dev: Device to poll. Unused - */ -void cvm_oct_poll_controller(struct net_device *dev) -{ - int i; - - if (!atomic_read(&oct_rx_ready)) - return; - - for (i = 0; i < ARRAY_SIZE(oct_rx_group); i++) { - if (!(pow_receive_groups & BIT(i))) - continue; - - cvm_oct_poll(&oct_rx_group[i], 16); - } -} -#endif - -void cvm_oct_rx_initialize(void) -{ - int i; - struct net_device *dev_for_napi = NULL; - - for (i = 0; i < TOTAL_NUMBER_OF_PORTS; i++) { - if (cvm_oct_device[i]) { - dev_for_napi = cvm_oct_device[i]; - break; - } - } - - if (!dev_for_napi) - panic("No net_devices were allocated."); - - for (i = 0; i < ARRAY_SIZE(oct_rx_group); i++) { - int ret; - - if (!(pow_receive_groups & BIT(i))) - continue; - - netif_napi_add(dev_for_napi, &oct_rx_group[i].napi, - cvm_oct_napi_poll, rx_napi_weight); - napi_enable(&oct_rx_group[i].napi); - - oct_rx_group[i].irq = OCTEON_IRQ_WORKQ0 + i; - oct_rx_group[i].group = i; - - /* Register an IRQ handler to receive POW interrupts */ - ret = request_irq(oct_rx_group[i].irq, cvm_oct_do_interrupt, 0, - "Ethernet", &oct_rx_group[i].napi); - if (ret) - panic("Could not acquire Ethernet IRQ %d\n", - oct_rx_group[i].irq); - - disable_irq_nosync(oct_rx_group[i].irq); - - /* Enable POW interrupt when our port has at least one packet */ - if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { - union cvmx_sso_wq_int_thrx int_thr; - union cvmx_pow_wq_int_pc int_pc; - - int_thr.u64 = 0; - int_thr.s.tc_en = 1; - int_thr.s.tc_thr = 1; - cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(i), int_thr.u64); - - int_pc.u64 = 0; - int_pc.s.pc_thr = 5; - cvmx_write_csr(CVMX_SSO_WQ_INT_PC, int_pc.u64); - } else { - union cvmx_pow_wq_int_thrx int_thr; - union cvmx_pow_wq_int_pc int_pc; - - int_thr.u64 = 0; - int_thr.s.tc_en = 1; - int_thr.s.tc_thr = 1; - cvmx_write_csr(CVMX_POW_WQ_INT_THRX(i), int_thr.u64); - - int_pc.u64 = 0; - int_pc.s.pc_thr = 5; - cvmx_write_csr(CVMX_POW_WQ_INT_PC, int_pc.u64); - } - - /* Schedule NAPI now. This will indirectly enable the - * interrupt. - */ - napi_schedule(&oct_rx_group[i].napi); - } - atomic_inc(&oct_rx_ready); -} - -void cvm_oct_rx_shutdown(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(oct_rx_group); i++) { - if (!(pow_receive_groups & BIT(i))) - continue; - - /* Disable POW interrupt */ - if (OCTEON_IS_MODEL(OCTEON_CN68XX)) - cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(i), 0); - else - cvmx_write_csr(CVMX_POW_WQ_INT_THRX(i), 0); - - /* Free the interrupt handler */ - free_irq(oct_rx_group[i].irq, cvm_oct_device); - - netif_napi_del(&oct_rx_group[i].napi); - } -} diff --git a/drivers/staging/octeon/ethernet-rx.h b/drivers/staging/octeon/ethernet-rx.h deleted file mode 100644 index ff6482fa20d6..000000000000 --- a/drivers/staging/octeon/ethernet-rx.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2007 Cavium Networks - */ - -void cvm_oct_poll_controller(struct net_device *dev); -void cvm_oct_rx_initialize(void); -void cvm_oct_rx_shutdown(void); - -static inline void cvm_oct_rx_refill_pool(int fill_threshold) -{ - int number_to_free; - int num_freed; - /* Refill the packet buffer pool */ - number_to_free = - cvmx_fau_fetch_and_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); - - if (number_to_free > fill_threshold) { - cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, - -number_to_free); - num_freed = cvm_oct_mem_fill_fpa(CVMX_FPA_PACKET_POOL, - CVMX_FPA_PACKET_POOL_SIZE, - number_to_free); - if (num_freed != number_to_free) { - cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, - number_to_free - num_freed); - } - } -} diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c deleted file mode 100644 index d7fbd9159302..000000000000 --- a/drivers/staging/octeon/ethernet-sgmii.c +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2007 Cavium Networks - */ - -#include -#include -#include -#include -#include - -#include "octeon-ethernet.h" -#include "ethernet-defines.h" -#include "ethernet-util.h" -#include "ethernet-mdio.h" - -int cvm_oct_sgmii_open(struct net_device *dev) -{ - return cvm_oct_common_open(dev, cvm_oct_link_poll); -} - -int cvm_oct_sgmii_init(struct net_device *dev) -{ - cvm_oct_common_init(dev); - - /* FIXME: Need autoneg logic */ - return 0; -} diff --git a/drivers/staging/octeon/ethernet-spi.c b/drivers/staging/octeon/ethernet-spi.c deleted file mode 100644 index c582403e6a1f..000000000000 --- a/drivers/staging/octeon/ethernet-spi.c +++ /dev/null @@ -1,226 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2007 Cavium Networks - */ - -#include -#include -#include -#include - -#include "octeon-ethernet.h" -#include "ethernet-defines.h" -#include "ethernet-util.h" - -static int number_spi_ports; -static int need_retrain[2] = { 0, 0 }; - -static void cvm_oct_spxx_int_pr(union cvmx_spxx_int_reg spx_int_reg, int index) -{ - if (spx_int_reg.s.spf) - pr_err("SPI%d: SRX Spi4 interface down\n", index); - if (spx_int_reg.s.calerr) - pr_err("SPI%d: SRX Spi4 Calendar table parity error\n", index); - if (spx_int_reg.s.syncerr) - pr_err("SPI%d: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n", - index); - if (spx_int_reg.s.diperr) - pr_err("SPI%d: SRX Spi4 DIP4 error\n", index); - if (spx_int_reg.s.tpaovr) - pr_err("SPI%d: SRX Selected port has hit TPA overflow\n", - index); - if (spx_int_reg.s.rsverr) - pr_err("SPI%d: SRX Spi4 reserved control word detected\n", - index); - if (spx_int_reg.s.drwnng) - pr_err("SPI%d: SRX Spi4 receive FIFO drowning/overflow\n", - index); - if (spx_int_reg.s.clserr) - pr_err("SPI%d: SRX Spi4 packet closed on non-16B alignment without EOP\n", - index); - if (spx_int_reg.s.spiovr) - pr_err("SPI%d: SRX Spi4 async FIFO overflow\n", index); - if (spx_int_reg.s.abnorm) - pr_err("SPI%d: SRX Abnormal packet termination (ERR bit)\n", - index); - if (spx_int_reg.s.prtnxa) - pr_err("SPI%d: SRX Port out of range\n", index); -} - -static void cvm_oct_stxx_int_pr(union cvmx_stxx_int_reg stx_int_reg, int index) -{ - if (stx_int_reg.s.syncerr) - pr_err("SPI%d: STX Interface encountered a fatal error\n", - index); - if (stx_int_reg.s.frmerr) - pr_err("SPI%d: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n", - index); - if (stx_int_reg.s.unxfrm) - pr_err("SPI%d: STX Unexpected framing sequence\n", index); - if (stx_int_reg.s.nosync) - pr_err("SPI%d: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n", - index); - if (stx_int_reg.s.diperr) - pr_err("SPI%d: STX DIP2 error on the Spi4 Status channel\n", - index); - if (stx_int_reg.s.datovr) - pr_err("SPI%d: STX Spi4 FIFO overflow error\n", index); - if (stx_int_reg.s.ovrbst) - pr_err("SPI%d: STX Transmit packet burst too big\n", index); - if (stx_int_reg.s.calpar1) - pr_err("SPI%d: STX Calendar Table Parity Error Bank%d\n", - index, 1); - if (stx_int_reg.s.calpar0) - pr_err("SPI%d: STX Calendar Table Parity Error Bank%d\n", - index, 0); -} - -static irqreturn_t cvm_oct_spi_spx_int(int index) -{ - union cvmx_spxx_int_reg spx_int_reg; - union cvmx_stxx_int_reg stx_int_reg; - - spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(index)); - cvmx_write_csr(CVMX_SPXX_INT_REG(index), spx_int_reg.u64); - if (!need_retrain[index]) { - spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(index)); - cvm_oct_spxx_int_pr(spx_int_reg, index); - } - - stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(index)); - cvmx_write_csr(CVMX_STXX_INT_REG(index), stx_int_reg.u64); - if (!need_retrain[index]) { - stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(index)); - cvm_oct_stxx_int_pr(stx_int_reg, index); - } - - cvmx_write_csr(CVMX_SPXX_INT_MSK(index), 0); - cvmx_write_csr(CVMX_STXX_INT_MSK(index), 0); - need_retrain[index] = 1; - - return IRQ_HANDLED; -} - -static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) -{ - irqreturn_t return_status = IRQ_NONE; - union cvmx_npi_rsl_int_blocks rsl_int_blocks; - - /* Check and see if this interrupt was caused by the GMX block */ - rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS); - if (rsl_int_blocks.s.spx1) /* 19 - SPX1_INT_REG & STX1_INT_REG */ - return_status = cvm_oct_spi_spx_int(1); - - if (rsl_int_blocks.s.spx0) /* 18 - SPX0_INT_REG & STX0_INT_REG */ - return_status = cvm_oct_spi_spx_int(0); - - return return_status; -} - -static void cvm_oct_spi_enable_error_reporting(int interface) -{ - union cvmx_spxx_int_msk spxx_int_msk; - union cvmx_stxx_int_msk stxx_int_msk; - - spxx_int_msk.u64 = cvmx_read_csr(CVMX_SPXX_INT_MSK(interface)); - spxx_int_msk.s.calerr = 1; - spxx_int_msk.s.syncerr = 1; - spxx_int_msk.s.diperr = 1; - spxx_int_msk.s.tpaovr = 1; - spxx_int_msk.s.rsverr = 1; - spxx_int_msk.s.drwnng = 1; - spxx_int_msk.s.clserr = 1; - spxx_int_msk.s.spiovr = 1; - spxx_int_msk.s.abnorm = 1; - spxx_int_msk.s.prtnxa = 1; - cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), spxx_int_msk.u64); - - stxx_int_msk.u64 = cvmx_read_csr(CVMX_STXX_INT_MSK(interface)); - stxx_int_msk.s.frmerr = 1; - stxx_int_msk.s.unxfrm = 1; - stxx_int_msk.s.nosync = 1; - stxx_int_msk.s.diperr = 1; - stxx_int_msk.s.datovr = 1; - stxx_int_msk.s.ovrbst = 1; - stxx_int_msk.s.calpar1 = 1; - stxx_int_msk.s.calpar0 = 1; - cvmx_write_csr(CVMX_STXX_INT_MSK(interface), stxx_int_msk.u64); -} - -static void cvm_oct_spi_poll(struct net_device *dev) -{ - static int spi4000_port; - struct octeon_ethernet *priv = netdev_priv(dev); - int interface; - - for (interface = 0; interface < 2; interface++) { - if ((priv->port == interface * 16) && need_retrain[interface]) { - if (cvmx_spi_restart_interface - (interface, CVMX_SPI_MODE_DUPLEX, 10) == 0) { - need_retrain[interface] = 0; - cvm_oct_spi_enable_error_reporting(interface); - } - } - - /* - * The SPI4000 TWSI interface is very slow. In order - * not to bring the system to a crawl, we only poll a - * single port every second. This means negotiation - * speed changes take up to 10 seconds, but at least - * we don't waste absurd amounts of time waiting for - * TWSI. - */ - if (priv->port == spi4000_port) { - /* - * This function does nothing if it is called on an - * interface without a SPI4000. - */ - cvmx_spi4000_check_speed(interface, priv->port); - /* - * Normal ordering increments. By decrementing - * we only match once per iteration. - */ - spi4000_port--; - if (spi4000_port < 0) - spi4000_port = 10; - } - } -} - -int cvm_oct_spi_init(struct net_device *dev) -{ - int r; - struct octeon_ethernet *priv = netdev_priv(dev); - - if (number_spi_ports == 0) { - r = request_irq(OCTEON_IRQ_RML, cvm_oct_spi_rml_interrupt, - IRQF_SHARED, "SPI", &number_spi_ports); - if (r) - return r; - } - number_spi_ports++; - - if ((priv->port == 0) || (priv->port == 16)) { - cvm_oct_spi_enable_error_reporting(INTERFACE(priv->port)); - priv->poll = cvm_oct_spi_poll; - } - cvm_oct_common_init(dev); - return 0; -} - -void cvm_oct_spi_uninit(struct net_device *dev) -{ - int interface; - - cvm_oct_common_uninit(dev); - number_spi_ports--; - if (number_spi_ports == 0) { - for (interface = 0; interface < 2; interface++) { - cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0); - cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0); - } - free_irq(OCTEON_IRQ_RML, &number_spi_ports); - } -} diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c deleted file mode 100644 index b334cf89794e..000000000000 --- a/drivers/staging/octeon/ethernet-tx.c +++ /dev/null @@ -1,717 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2010 Cavium Networks - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_XFRM -#include -#include -#endif /* CONFIG_XFRM */ - -#include -#include - -#include "octeon-ethernet.h" -#include "ethernet-defines.h" -#include "ethernet-tx.h" -#include "ethernet-util.h" - -#define CVM_OCT_SKB_CB(skb) ((u64 *)((skb)->cb)) - -/* - * You can define GET_SKBUFF_QOS() to override how the skbuff output - * function determines which output queue is used. The default - * implementation always uses the base queue for the port. If, for - * example, you wanted to use the skb->priority field, define - * GET_SKBUFF_QOS as: #define GET_SKBUFF_QOS(skb) ((skb)->priority) - */ -#ifndef GET_SKBUFF_QOS -#define GET_SKBUFF_QOS(skb) 0 -#endif - -static void cvm_oct_tx_do_cleanup(unsigned long arg); -static DECLARE_TASKLET(cvm_oct_tx_cleanup_tasklet, cvm_oct_tx_do_cleanup, 0); - -/* Maximum number of SKBs to try to free per xmit packet. */ -#define MAX_SKB_TO_FREE (MAX_OUT_QUEUE_DEPTH * 2) - -static inline int cvm_oct_adjust_skb_to_free(int skb_to_free, int fau) -{ - int undo; - - undo = skb_to_free > 0 ? MAX_SKB_TO_FREE : skb_to_free + - MAX_SKB_TO_FREE; - if (undo > 0) - cvmx_fau_atomic_add32(fau, -undo); - skb_to_free = -skb_to_free > MAX_SKB_TO_FREE ? MAX_SKB_TO_FREE : - -skb_to_free; - return skb_to_free; -} - -static void cvm_oct_kick_tx_poll_watchdog(void) -{ - union cvmx_ciu_timx ciu_timx; - - ciu_timx.u64 = 0; - ciu_timx.s.one_shot = 1; - ciu_timx.s.len = cvm_oct_tx_poll_interval; - cvmx_write_csr(CVMX_CIU_TIMX(1), ciu_timx.u64); -} - -static void cvm_oct_free_tx_skbs(struct net_device *dev) -{ - int skb_to_free; - int qos, queues_per_port; - int total_freed = 0; - int total_remaining = 0; - unsigned long flags; - struct octeon_ethernet *priv = netdev_priv(dev); - - queues_per_port = cvmx_pko_get_num_queues(priv->port); - /* Drain any pending packets in the free list */ - for (qos = 0; qos < queues_per_port; qos++) { - if (skb_queue_len(&priv->tx_free_list[qos]) == 0) - continue; - skb_to_free = cvmx_fau_fetch_and_add32(priv->fau + qos * 4, - MAX_SKB_TO_FREE); - skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, - priv->fau + qos * 4); - total_freed += skb_to_free; - if (skb_to_free > 0) { - struct sk_buff *to_free_list = NULL; - - spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); - while (skb_to_free > 0) { - struct sk_buff *t; - - t = __skb_dequeue(&priv->tx_free_list[qos]); - t->next = to_free_list; - to_free_list = t; - skb_to_free--; - } - spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, - flags); - /* Do the actual freeing outside of the lock. */ - while (to_free_list) { - struct sk_buff *t = to_free_list; - - to_free_list = to_free_list->next; - dev_kfree_skb_any(t); - } - } - total_remaining += skb_queue_len(&priv->tx_free_list[qos]); - } - if (total_remaining < MAX_OUT_QUEUE_DEPTH && netif_queue_stopped(dev)) - netif_wake_queue(dev); - if (total_remaining) - cvm_oct_kick_tx_poll_watchdog(); -} - -/** - * cvm_oct_xmit - transmit a packet - * @skb: Packet to send - * @dev: Device info structure - * - * Returns Always returns NETDEV_TX_OK - */ -int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) -{ - union cvmx_pko_command_word0 pko_command; - union cvmx_buf_ptr hw_buffer; - u64 old_scratch; - u64 old_scratch2; - int qos; - int i; - enum {QUEUE_CORE, QUEUE_HW, QUEUE_DROP} queue_type; - struct octeon_ethernet *priv = netdev_priv(dev); - struct sk_buff *to_free_list; - int skb_to_free; - int buffers_to_free; - u32 total_to_clean; - unsigned long flags; -#if REUSE_SKBUFFS_WITHOUT_FREE - unsigned char *fpa_head; -#endif - - /* - * Prefetch the private data structure. It is larger than the - * one cache line. - */ - prefetch(priv); - - /* - * The check on CVMX_PKO_QUEUES_PER_PORT_* is designed to - * completely remove "qos" in the event neither interface - * supports multiple queues per port. - */ - if ((CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 > 1) || - (CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 > 1)) { - qos = GET_SKBUFF_QOS(skb); - if (qos <= 0) - qos = 0; - else if (qos >= cvmx_pko_get_num_queues(priv->port)) - qos = 0; - } else { - qos = 0; - } - - if (USE_ASYNC_IOBDMA) { - /* Save scratch in case userspace is using it */ - CVMX_SYNCIOBDMA; - old_scratch = cvmx_scratch_read64(CVMX_SCR_SCRATCH); - old_scratch2 = cvmx_scratch_read64(CVMX_SCR_SCRATCH + 8); - - /* - * Fetch and increment the number of packets to be - * freed. - */ - cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH + 8, - FAU_NUM_PACKET_BUFFERS_TO_FREE, - 0); - cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH, - priv->fau + qos * 4, - MAX_SKB_TO_FREE); - } - - /* - * We have space for 6 segment pointers, If there will be more - * than that, we must linearize. - */ - if (unlikely(skb_shinfo(skb)->nr_frags > 5)) { - if (unlikely(__skb_linearize(skb))) { - queue_type = QUEUE_DROP; - if (USE_ASYNC_IOBDMA) { - /* - * Get the number of skbuffs in use - * by the hardware - */ - CVMX_SYNCIOBDMA; - skb_to_free = - cvmx_scratch_read64(CVMX_SCR_SCRATCH); - } else { - /* - * Get the number of skbuffs in use - * by the hardware - */ - skb_to_free = - cvmx_fau_fetch_and_add32(priv->fau + - qos * 4, - MAX_SKB_TO_FREE); - } - skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, - priv->fau + - qos * 4); - spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); - goto skip_xmit; - } - } - - /* - * The CN3XXX series of parts has an errata (GMX-401) which - * causes the GMX block to hang if a collision occurs towards - * the end of a <68 byte packet. As a workaround for this, we - * pad packets to be 68 bytes whenever we are in half duplex - * mode. We don't handle the case of having a small packet but - * no room to add the padding. The kernel should always give - * us at least a cache line - */ - if ((skb->len < 64) && OCTEON_IS_MODEL(OCTEON_CN3XXX)) { - union cvmx_gmxx_prtx_cfg gmx_prt_cfg; - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - - if (interface < 2) { - /* We only need to pad packet in half duplex mode */ - gmx_prt_cfg.u64 = - cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); - if (gmx_prt_cfg.s.duplex == 0) { - int add_bytes = 64 - skb->len; - - if ((skb_tail_pointer(skb) + add_bytes) <= - skb_end_pointer(skb)) - __skb_put_zero(skb, add_bytes); - } - } - } - - /* Build the PKO command */ - pko_command.u64 = 0; -#ifdef __LITTLE_ENDIAN - pko_command.s.le = 1; -#endif - pko_command.s.n2 = 1; /* Don't pollute L2 with the outgoing packet */ - pko_command.s.segs = 1; - pko_command.s.total_bytes = skb->len; - pko_command.s.size0 = CVMX_FAU_OP_SIZE_32; - pko_command.s.subone0 = 1; - - pko_command.s.dontfree = 1; - - /* Build the PKO buffer pointer */ - hw_buffer.u64 = 0; - if (skb_shinfo(skb)->nr_frags == 0) { - hw_buffer.s.addr = XKPHYS_TO_PHYS((uintptr_t)skb->data); - hw_buffer.s.pool = 0; - hw_buffer.s.size = skb->len; - } else { - hw_buffer.s.addr = XKPHYS_TO_PHYS((uintptr_t)skb->data); - hw_buffer.s.pool = 0; - hw_buffer.s.size = skb_headlen(skb); - CVM_OCT_SKB_CB(skb)[0] = hw_buffer.u64; - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - skb_frag_t *fs = skb_shinfo(skb)->frags + i; - - hw_buffer.s.addr = - XKPHYS_TO_PHYS((uintptr_t)skb_frag_address(fs)); - hw_buffer.s.size = skb_frag_size(fs); - CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64; - } - hw_buffer.s.addr = - XKPHYS_TO_PHYS((uintptr_t)CVM_OCT_SKB_CB(skb)); - hw_buffer.s.size = skb_shinfo(skb)->nr_frags + 1; - pko_command.s.segs = skb_shinfo(skb)->nr_frags + 1; - pko_command.s.gather = 1; - goto dont_put_skbuff_in_hw; - } - - /* - * See if we can put this skb in the FPA pool. Any strange - * behavior from the Linux networking stack will most likely - * be caused by a bug in the following code. If some field is - * in use by the network stack and gets carried over when a - * buffer is reused, bad things may happen. If in doubt and - * you dont need the absolute best performance, disable the - * define REUSE_SKBUFFS_WITHOUT_FREE. The reuse of buffers has - * shown a 25% increase in performance under some loads. - */ -#if REUSE_SKBUFFS_WITHOUT_FREE - fpa_head = skb->head + 256 - ((unsigned long)skb->head & 0x7f); - if (unlikely(skb->data < fpa_head)) { - /* TX buffer beginning can't meet FPA alignment constraints */ - goto dont_put_skbuff_in_hw; - } - if (unlikely - ((skb_end_pointer(skb) - fpa_head) < CVMX_FPA_PACKET_POOL_SIZE)) { - /* TX buffer isn't large enough for the FPA */ - goto dont_put_skbuff_in_hw; - } - if (unlikely(skb_shared(skb))) { - /* TX buffer sharing data with someone else */ - goto dont_put_skbuff_in_hw; - } - if (unlikely(skb_cloned(skb))) { - /* TX buffer has been cloned */ - goto dont_put_skbuff_in_hw; - } - if (unlikely(skb_header_cloned(skb))) { - /* TX buffer header has been cloned */ - goto dont_put_skbuff_in_hw; - } - if (unlikely(skb->destructor)) { - /* TX buffer has a destructor */ - goto dont_put_skbuff_in_hw; - } - if (unlikely(skb_shinfo(skb)->nr_frags)) { - /* TX buffer has fragments */ - goto dont_put_skbuff_in_hw; - } - if (unlikely - (skb->truesize != - sizeof(*skb) + skb_end_offset(skb))) { - /* TX buffer truesize has been changed */ - goto dont_put_skbuff_in_hw; - } - - /* - * We can use this buffer in the FPA. We don't need the FAU - * update anymore - */ - pko_command.s.dontfree = 0; - - hw_buffer.s.back = ((unsigned long)skb->data >> 7) - - ((unsigned long)fpa_head >> 7); - - *(struct sk_buff **)(fpa_head - sizeof(void *)) = skb; - - /* - * The skbuff will be reused without ever being freed. We must - * cleanup a bunch of core things. - */ - dst_release(skb_dst(skb)); - skb_dst_set(skb, NULL); - skb_ext_reset(skb); - nf_reset_ct(skb); - -#ifdef CONFIG_NET_SCHED - skb->tc_index = 0; - skb_reset_tc(skb); -#endif /* CONFIG_NET_SCHED */ -#endif /* REUSE_SKBUFFS_WITHOUT_FREE */ - -dont_put_skbuff_in_hw: - - /* Check if we can use the hardware checksumming */ - if ((skb->protocol == htons(ETH_P_IP)) && - (ip_hdr(skb)->version == 4) && - (ip_hdr(skb)->ihl == 5) && - ((ip_hdr(skb)->frag_off == 0) || - (ip_hdr(skb)->frag_off == htons(1 << 14))) && - ((ip_hdr(skb)->protocol == IPPROTO_TCP) || - (ip_hdr(skb)->protocol == IPPROTO_UDP))) { - /* Use hardware checksum calc */ - pko_command.s.ipoffp1 = skb_network_offset(skb) + 1; - } - - if (USE_ASYNC_IOBDMA) { - /* Get the number of skbuffs in use by the hardware */ - CVMX_SYNCIOBDMA; - skb_to_free = cvmx_scratch_read64(CVMX_SCR_SCRATCH); - buffers_to_free = cvmx_scratch_read64(CVMX_SCR_SCRATCH + 8); - } else { - /* Get the number of skbuffs in use by the hardware */ - skb_to_free = cvmx_fau_fetch_and_add32(priv->fau + qos * 4, - MAX_SKB_TO_FREE); - buffers_to_free = - cvmx_fau_fetch_and_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); - } - - skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, - priv->fau + qos * 4); - - /* - * If we're sending faster than the receive can free them then - * don't do the HW free. - */ - if ((buffers_to_free < -100) && !pko_command.s.dontfree) - pko_command.s.dontfree = 1; - - if (pko_command.s.dontfree) { - queue_type = QUEUE_CORE; - pko_command.s.reg0 = priv->fau + qos * 4; - } else { - queue_type = QUEUE_HW; - } - if (USE_ASYNC_IOBDMA) - cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH, - FAU_TOTAL_TX_TO_CLEAN, 1); - - spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); - - /* Drop this packet if we have too many already queued to the HW */ - if (unlikely(skb_queue_len(&priv->tx_free_list[qos]) >= - MAX_OUT_QUEUE_DEPTH)) { - if (dev->tx_queue_len != 0) { - /* Drop the lock when notifying the core. */ - spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, - flags); - netif_stop_queue(dev); - spin_lock_irqsave(&priv->tx_free_list[qos].lock, - flags); - } else { - /* If not using normal queueing. */ - queue_type = QUEUE_DROP; - goto skip_xmit; - } - } - - cvmx_pko_send_packet_prepare(priv->port, priv->queue + qos, - CVMX_PKO_LOCK_NONE); - - /* Send the packet to the output queue */ - if (unlikely(cvmx_pko_send_packet_finish(priv->port, - priv->queue + qos, - pko_command, hw_buffer, - CVMX_PKO_LOCK_NONE))) { - printk_ratelimited("%s: Failed to send the packet\n", - dev->name); - queue_type = QUEUE_DROP; - } -skip_xmit: - to_free_list = NULL; - - switch (queue_type) { - case QUEUE_DROP: - skb->next = to_free_list; - to_free_list = skb; - dev->stats.tx_dropped++; - break; - case QUEUE_HW: - cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, -1); - break; - case QUEUE_CORE: - __skb_queue_tail(&priv->tx_free_list[qos], skb); - break; - default: - BUG(); - } - - while (skb_to_free > 0) { - struct sk_buff *t = __skb_dequeue(&priv->tx_free_list[qos]); - - t->next = to_free_list; - to_free_list = t; - skb_to_free--; - } - - spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, flags); - - /* Do the actual freeing outside of the lock. */ - while (to_free_list) { - struct sk_buff *t = to_free_list; - - to_free_list = to_free_list->next; - dev_kfree_skb_any(t); - } - - if (USE_ASYNC_IOBDMA) { - CVMX_SYNCIOBDMA; - total_to_clean = cvmx_scratch_read64(CVMX_SCR_SCRATCH); - /* Restore the scratch area */ - cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch); - cvmx_scratch_write64(CVMX_SCR_SCRATCH + 8, old_scratch2); - } else { - total_to_clean = - cvmx_fau_fetch_and_add32(FAU_TOTAL_TX_TO_CLEAN, 1); - } - - if (total_to_clean & 0x3ff) { - /* - * Schedule the cleanup tasklet every 1024 packets for - * the pathological case of high traffic on one port - * delaying clean up of packets on a different port - * that is blocked waiting for the cleanup. - */ - tasklet_schedule(&cvm_oct_tx_cleanup_tasklet); - } - - cvm_oct_kick_tx_poll_watchdog(); - - return NETDEV_TX_OK; -} - -/** - * cvm_oct_xmit_pow - transmit a packet to the POW - * @skb: Packet to send - * @dev: Device info structure - - * Returns Always returns zero - */ -int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - void *packet_buffer; - void *copy_location; - - /* Get a work queue entry */ - struct cvmx_wqe *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL); - - if (unlikely(!work)) { - printk_ratelimited("%s: Failed to allocate a work queue entry\n", - dev->name); - dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - return 0; - } - - /* Get a packet buffer */ - packet_buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL); - if (unlikely(!packet_buffer)) { - printk_ratelimited("%s: Failed to allocate a packet buffer\n", - dev->name); - cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 1); - dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - return 0; - } - - /* - * Calculate where we need to copy the data to. We need to - * leave 8 bytes for a next pointer (unused). We also need to - * include any configure skip. Then we need to align the IP - * packet src and dest into the same 64bit word. The below - * calculation may add a little extra, but that doesn't - * hurt. - */ - copy_location = packet_buffer + sizeof(u64); - copy_location += ((CVMX_HELPER_FIRST_MBUFF_SKIP + 7) & 0xfff8) + 6; - - /* - * We have to copy the packet since whoever processes this - * packet will free it to a hardware pool. We can't use the - * trick of counting outstanding packets like in - * cvm_oct_xmit. - */ - memcpy(copy_location, skb->data, skb->len); - - /* - * Fill in some of the work queue fields. We may need to add - * more if the software at the other end needs them. - */ - if (!OCTEON_IS_MODEL(OCTEON_CN68XX)) - work->word0.pip.cn38xx.hw_chksum = skb->csum; - work->word1.len = skb->len; - cvmx_wqe_set_port(work, priv->port); - cvmx_wqe_set_qos(work, priv->port & 0x7); - cvmx_wqe_set_grp(work, pow_send_group); - work->word1.tag_type = CVMX_HELPER_INPUT_TAG_TYPE; - work->word1.tag = pow_send_group; /* FIXME */ - /* Default to zero. Sets of zero later are commented out */ - work->word2.u64 = 0; - work->word2.s.bufs = 1; - work->packet_ptr.u64 = 0; - work->packet_ptr.s.addr = cvmx_ptr_to_phys(copy_location); - work->packet_ptr.s.pool = CVMX_FPA_PACKET_POOL; - work->packet_ptr.s.size = CVMX_FPA_PACKET_POOL_SIZE; - work->packet_ptr.s.back = (copy_location - packet_buffer) >> 7; - - if (skb->protocol == htons(ETH_P_IP)) { - work->word2.s.ip_offset = 14; -#if 0 - work->word2.s.vlan_valid = 0; /* FIXME */ - work->word2.s.vlan_cfi = 0; /* FIXME */ - work->word2.s.vlan_id = 0; /* FIXME */ - work->word2.s.dec_ipcomp = 0; /* FIXME */ -#endif - work->word2.s.tcp_or_udp = - (ip_hdr(skb)->protocol == IPPROTO_TCP) || - (ip_hdr(skb)->protocol == IPPROTO_UDP); -#if 0 - /* FIXME */ - work->word2.s.dec_ipsec = 0; - /* We only support IPv4 right now */ - work->word2.s.is_v6 = 0; - /* Hardware would set to zero */ - work->word2.s.software = 0; - /* No error, packet is internal */ - work->word2.s.L4_error = 0; -#endif - work->word2.s.is_frag = !((ip_hdr(skb)->frag_off == 0) || - (ip_hdr(skb)->frag_off == - cpu_to_be16(1 << 14))); -#if 0 - /* Assume Linux is sending a good packet */ - work->word2.s.IP_exc = 0; -#endif - work->word2.s.is_bcast = (skb->pkt_type == PACKET_BROADCAST); - work->word2.s.is_mcast = (skb->pkt_type == PACKET_MULTICAST); -#if 0 - /* This is an IP packet */ - work->word2.s.not_IP = 0; - /* No error, packet is internal */ - work->word2.s.rcv_error = 0; - /* No error, packet is internal */ - work->word2.s.err_code = 0; -#endif - - /* - * When copying the data, include 4 bytes of the - * ethernet header to align the same way hardware - * does. - */ - memcpy(work->packet_data, skb->data + 10, - sizeof(work->packet_data)); - } else { -#if 0 - work->word2.snoip.vlan_valid = 0; /* FIXME */ - work->word2.snoip.vlan_cfi = 0; /* FIXME */ - work->word2.snoip.vlan_id = 0; /* FIXME */ - work->word2.snoip.software = 0; /* Hardware would set to zero */ -#endif - work->word2.snoip.is_rarp = skb->protocol == htons(ETH_P_RARP); - work->word2.snoip.is_arp = skb->protocol == htons(ETH_P_ARP); - work->word2.snoip.is_bcast = - (skb->pkt_type == PACKET_BROADCAST); - work->word2.snoip.is_mcast = - (skb->pkt_type == PACKET_MULTICAST); - work->word2.snoip.not_IP = 1; /* IP was done up above */ -#if 0 - /* No error, packet is internal */ - work->word2.snoip.rcv_error = 0; - /* No error, packet is internal */ - work->word2.snoip.err_code = 0; -#endif - memcpy(work->packet_data, skb->data, sizeof(work->packet_data)); - } - - /* Submit the packet to the POW */ - cvmx_pow_work_submit(work, work->word1.tag, work->word1.tag_type, - cvmx_wqe_get_qos(work), cvmx_wqe_get_grp(work)); - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - dev_consume_skb_any(skb); - return 0; -} - -/** - * cvm_oct_tx_shutdown_dev - free all skb that are currently queued for TX. - * @dev: Device being shutdown - * - */ -void cvm_oct_tx_shutdown_dev(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - unsigned long flags; - int qos; - - for (qos = 0; qos < 16; qos++) { - spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); - while (skb_queue_len(&priv->tx_free_list[qos])) - dev_kfree_skb_any(__skb_dequeue - (&priv->tx_free_list[qos])); - spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, flags); - } -} - -static void cvm_oct_tx_do_cleanup(unsigned long arg) -{ - int port; - - for (port = 0; port < TOTAL_NUMBER_OF_PORTS; port++) { - if (cvm_oct_device[port]) { - struct net_device *dev = cvm_oct_device[port]; - - cvm_oct_free_tx_skbs(dev); - } - } -} - -static irqreturn_t cvm_oct_tx_cleanup_watchdog(int cpl, void *dev_id) -{ - /* Disable the interrupt. */ - cvmx_write_csr(CVMX_CIU_TIMX(1), 0); - /* Do the work in the tasklet. */ - tasklet_schedule(&cvm_oct_tx_cleanup_tasklet); - return IRQ_HANDLED; -} - -void cvm_oct_tx_initialize(void) -{ - int i; - - /* Disable the interrupt. */ - cvmx_write_csr(CVMX_CIU_TIMX(1), 0); - /* Register an IRQ handler to receive CIU_TIMX(1) interrupts */ - i = request_irq(OCTEON_IRQ_TIMER1, - cvm_oct_tx_cleanup_watchdog, 0, - "Ethernet", cvm_oct_device); - - if (i) - panic("Could not acquire Ethernet IRQ %d\n", OCTEON_IRQ_TIMER1); -} - -void cvm_oct_tx_shutdown(void) -{ - /* Free the interrupt handler */ - free_irq(OCTEON_IRQ_TIMER1, cvm_oct_device); -} diff --git a/drivers/staging/octeon/ethernet-tx.h b/drivers/staging/octeon/ethernet-tx.h deleted file mode 100644 index 78936e9b33b0..000000000000 --- a/drivers/staging/octeon/ethernet-tx.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2007 Cavium Networks - */ - -int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev); -int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev); -int cvm_oct_transmit_qos(struct net_device *dev, void *work_queue_entry, - int do_free, int qos); -void cvm_oct_tx_initialize(void); -void cvm_oct_tx_shutdown(void); -void cvm_oct_tx_shutdown_dev(struct net_device *dev); diff --git a/drivers/staging/octeon/ethernet-util.h b/drivers/staging/octeon/ethernet-util.h deleted file mode 100644 index 2af83a12ca78..000000000000 --- a/drivers/staging/octeon/ethernet-util.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2007 Cavium Networks - */ - -/** - * cvm_oct_get_buffer_ptr - convert packet data address to pointer - * @packet_ptr: Packet data hardware address - * - * Returns Packet buffer pointer - */ -static inline void *cvm_oct_get_buffer_ptr(union cvmx_buf_ptr packet_ptr) -{ - return cvmx_phys_to_ptr(((packet_ptr.s.addr >> 7) - packet_ptr.s.back) - << 7); -} - -/** - * INTERFACE - convert IPD port to logical interface - * @ipd_port: Port to check - * - * Returns Logical interface - */ -static inline int INTERFACE(int ipd_port) -{ - int interface; - - if (ipd_port == CVMX_PIP_NUM_INPUT_PORTS) - return 10; - interface = cvmx_helper_get_interface_num(ipd_port); - if (interface >= 0) - return interface; - panic("Illegal ipd_port %d passed to %s\n", ipd_port, __func__); -} - -/** - * INDEX - convert IPD/PKO port number to the port's interface index - * @ipd_port: Port to check - * - * Returns Index into interface port list - */ -static inline int INDEX(int ipd_port) -{ - return cvmx_helper_get_interface_index_num(ipd_port); -} diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c deleted file mode 100644 index f42c3816ce49..000000000000 --- a/drivers/staging/octeon/ethernet.c +++ /dev/null @@ -1,992 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2007 Cavium Networks - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "octeon-ethernet.h" -#include "ethernet-defines.h" -#include "ethernet-mem.h" -#include "ethernet-rx.h" -#include "ethernet-tx.h" -#include "ethernet-mdio.h" -#include "ethernet-util.h" - -#define OCTEON_MAX_MTU 65392 - -static int num_packet_buffers = 1024; -module_param(num_packet_buffers, int, 0444); -MODULE_PARM_DESC(num_packet_buffers, "\n" - "\tNumber of packet buffers to allocate and store in the\n" - "\tFPA. By default, 1024 packet buffers are used.\n"); - -static int pow_receive_group = 15; -module_param(pow_receive_group, int, 0444); -MODULE_PARM_DESC(pow_receive_group, "\n" - "\tPOW group to receive packets from. All ethernet hardware\n" - "\twill be configured to send incoming packets to this POW\n" - "\tgroup. Also any other software can submit packets to this\n" - "\tgroup for the kernel to process."); - -static int receive_group_order; -module_param(receive_group_order, int, 0444); -MODULE_PARM_DESC(receive_group_order, "\n" - "\tOrder (0..4) of receive groups to take into use. Ethernet hardware\n" - "\twill be configured to send incoming packets to multiple POW\n" - "\tgroups. pow_receive_group parameter is ignored when multiple\n" - "\tgroups are taken into use and groups are allocated starting\n" - "\tfrom 0. By default, a single group is used.\n"); - -int pow_send_group = -1; -module_param(pow_send_group, int, 0644); -MODULE_PARM_DESC(pow_send_group, "\n" - "\tPOW group to send packets to other software on. This\n" - "\tcontrols the creation of the virtual device pow0.\n" - "\talways_use_pow also depends on this value."); - -int always_use_pow; -module_param(always_use_pow, int, 0444); -MODULE_PARM_DESC(always_use_pow, "\n" - "\tWhen set, always send to the pow group. This will cause\n" - "\tpackets sent to real ethernet devices to be sent to the\n" - "\tPOW group instead of the hardware. Unless some other\n" - "\tapplication changes the config, packets will still be\n" - "\treceived from the low level hardware. Use this option\n" - "\tto allow a CVMX app to intercept all packets from the\n" - "\tlinux kernel. You must specify pow_send_group along with\n" - "\tthis option."); - -char pow_send_list[128] = ""; -module_param_string(pow_send_list, pow_send_list, sizeof(pow_send_list), 0444); -MODULE_PARM_DESC(pow_send_list, "\n" - "\tComma separated list of ethernet devices that should use the\n" - "\tPOW for transmit instead of the actual ethernet hardware. This\n" - "\tis a per port version of always_use_pow. always_use_pow takes\n" - "\tprecedence over this list. For example, setting this to\n" - "\t\"eth2,spi3,spi7\" would cause these three devices to transmit\n" - "\tusing the pow_send_group."); - -int rx_napi_weight = 32; -module_param(rx_napi_weight, int, 0444); -MODULE_PARM_DESC(rx_napi_weight, "The NAPI WEIGHT parameter."); - -/* Mask indicating which receive groups are in use. */ -int pow_receive_groups; - -/* - * cvm_oct_poll_queue_stopping - flag to indicate polling should stop. - * - * Set to one right before cvm_oct_poll_queue is destroyed. - */ -atomic_t cvm_oct_poll_queue_stopping = ATOMIC_INIT(0); - -/* - * Array of every ethernet device owned by this driver indexed by - * the ipd input port number. - */ -struct net_device *cvm_oct_device[TOTAL_NUMBER_OF_PORTS]; - -u64 cvm_oct_tx_poll_interval; - -static void cvm_oct_rx_refill_worker(struct work_struct *work); -static DECLARE_DELAYED_WORK(cvm_oct_rx_refill_work, cvm_oct_rx_refill_worker); - -static void cvm_oct_rx_refill_worker(struct work_struct *work) -{ - /* - * FPA 0 may have been drained, try to refill it if we need - * more than num_packet_buffers / 2, otherwise normal receive - * processing will refill it. If it were drained, no packets - * could be received so cvm_oct_napi_poll would never be - * invoked to do the refill. - */ - cvm_oct_rx_refill_pool(num_packet_buffers / 2); - - if (!atomic_read(&cvm_oct_poll_queue_stopping)) - schedule_delayed_work(&cvm_oct_rx_refill_work, HZ); -} - -static void cvm_oct_periodic_worker(struct work_struct *work) -{ - struct octeon_ethernet *priv = container_of(work, - struct octeon_ethernet, - port_periodic_work.work); - - if (priv->poll) - priv->poll(cvm_oct_device[priv->port]); - - cvm_oct_device[priv->port]->netdev_ops->ndo_get_stats - (cvm_oct_device[priv->port]); - - if (!atomic_read(&cvm_oct_poll_queue_stopping)) - schedule_delayed_work(&priv->port_periodic_work, HZ); -} - -static void cvm_oct_configure_common_hw(void) -{ - /* Setup the FPA */ - cvmx_fpa_enable(); - cvm_oct_mem_fill_fpa(CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE, - num_packet_buffers); - cvm_oct_mem_fill_fpa(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE, - num_packet_buffers); - if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL) - cvm_oct_mem_fill_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL, - CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 1024); - -#ifdef __LITTLE_ENDIAN - { - union cvmx_ipd_ctl_status ipd_ctl_status; - - ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); - ipd_ctl_status.s.pkt_lend = 1; - ipd_ctl_status.s.wqe_lend = 1; - cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64); - } -#endif - - cvmx_helper_setup_red(num_packet_buffers / 4, num_packet_buffers / 8); -} - -/** - * cvm_oct_free_work- Free a work queue entry - * - * @work_queue_entry: Work queue entry to free - * - * Returns Zero on success, Negative on failure. - */ -int cvm_oct_free_work(void *work_queue_entry) -{ - struct cvmx_wqe *work = work_queue_entry; - - int segments = work->word2.s.bufs; - union cvmx_buf_ptr segment_ptr = work->packet_ptr; - - while (segments--) { - union cvmx_buf_ptr next_ptr = *(union cvmx_buf_ptr *) - cvmx_phys_to_ptr(segment_ptr.s.addr - 8); - if (unlikely(!segment_ptr.s.i)) - cvmx_fpa_free(cvm_oct_get_buffer_ptr(segment_ptr), - segment_ptr.s.pool, - CVMX_FPA_PACKET_POOL_SIZE / 128); - segment_ptr = next_ptr; - } - cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 1); - - return 0; -} -EXPORT_SYMBOL(cvm_oct_free_work); - -/** - * cvm_oct_common_get_stats - get the low level ethernet statistics - * @dev: Device to get the statistics from - * - * Returns Pointer to the statistics - */ -static struct net_device_stats *cvm_oct_common_get_stats(struct net_device *dev) -{ - cvmx_pip_port_status_t rx_status; - cvmx_pko_port_status_t tx_status; - struct octeon_ethernet *priv = netdev_priv(dev); - - if (priv->port < CVMX_PIP_NUM_INPUT_PORTS) { - if (octeon_is_simulation()) { - /* The simulator doesn't support statistics */ - memset(&rx_status, 0, sizeof(rx_status)); - memset(&tx_status, 0, sizeof(tx_status)); - } else { - cvmx_pip_get_port_status(priv->port, 1, &rx_status); - cvmx_pko_get_port_status(priv->port, 1, &tx_status); - } - - dev->stats.rx_packets += rx_status.inb_packets; - dev->stats.tx_packets += tx_status.packets; - dev->stats.rx_bytes += rx_status.inb_octets; - dev->stats.tx_bytes += tx_status.octets; - dev->stats.multicast += rx_status.multicast_packets; - dev->stats.rx_crc_errors += rx_status.inb_errors; - dev->stats.rx_frame_errors += rx_status.fcs_align_err_packets; - dev->stats.rx_dropped += rx_status.dropped_packets; - } - - return &dev->stats; -} - -/** - * cvm_oct_common_change_mtu - change the link MTU - * @dev: Device to change - * @new_mtu: The new MTU - * - * Returns Zero on success - */ -static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - int interface = INTERFACE(priv->port); -#if IS_ENABLED(CONFIG_VLAN_8021Q) - int vlan_bytes = VLAN_HLEN; -#else - int vlan_bytes = 0; -#endif - int mtu_overhead = ETH_HLEN + ETH_FCS_LEN + vlan_bytes; - - dev->mtu = new_mtu; - - if ((interface < 2) && - (cvmx_helper_interface_get_mode(interface) != - CVMX_HELPER_INTERFACE_MODE_SPI)) { - int index = INDEX(priv->port); - /* Add ethernet header and FCS, and VLAN if configured. */ - int max_packet = new_mtu + mtu_overhead; - - if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || - OCTEON_IS_MODEL(OCTEON_CN58XX)) { - /* Signal errors on packets larger than the MTU */ - cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX(index, interface), - max_packet); - } else { - /* - * Set the hardware to truncate packets larger - * than the MTU and smaller the 64 bytes. - */ - union cvmx_pip_frm_len_chkx frm_len_chk; - - frm_len_chk.u64 = 0; - frm_len_chk.s.minlen = VLAN_ETH_ZLEN; - frm_len_chk.s.maxlen = max_packet; - cvmx_write_csr(CVMX_PIP_FRM_LEN_CHKX(interface), - frm_len_chk.u64); - } - /* - * Set the hardware to truncate packets larger than - * the MTU. The jabber register must be set to a - * multiple of 8 bytes, so round up. - */ - cvmx_write_csr(CVMX_GMXX_RXX_JABBER(index, interface), - (max_packet + 7) & ~7u); - } - return 0; -} - -/** - * cvm_oct_common_set_multicast_list - set the multicast list - * @dev: Device to work on - */ -static void cvm_oct_common_set_multicast_list(struct net_device *dev) -{ - union cvmx_gmxx_prtx_cfg gmx_cfg; - struct octeon_ethernet *priv = netdev_priv(dev); - int interface = INTERFACE(priv->port); - - if ((interface < 2) && - (cvmx_helper_interface_get_mode(interface) != - CVMX_HELPER_INTERFACE_MODE_SPI)) { - union cvmx_gmxx_rxx_adr_ctl control; - int index = INDEX(priv->port); - - control.u64 = 0; - control.s.bcst = 1; /* Allow broadcast MAC addresses */ - - if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI) || - (dev->flags & IFF_PROMISC)) - /* Force accept multicast packets */ - control.s.mcst = 2; - else - /* Force reject multicast packets */ - control.s.mcst = 1; - - if (dev->flags & IFF_PROMISC) - /* - * Reject matches if promisc. Since CAM is - * shut off, should accept everything. - */ - control.s.cam_mode = 0; - else - /* Filter packets based on the CAM */ - control.s.cam_mode = 1; - - gmx_cfg.u64 = - cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), - gmx_cfg.u64 & ~1ull); - - cvmx_write_csr(CVMX_GMXX_RXX_ADR_CTL(index, interface), - control.u64); - if (dev->flags & IFF_PROMISC) - cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN - (index, interface), 0); - else - cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN - (index, interface), 1); - - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), - gmx_cfg.u64); - } -} - -static int cvm_oct_set_mac_filter(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - union cvmx_gmxx_prtx_cfg gmx_cfg; - int interface = INTERFACE(priv->port); - - if ((interface < 2) && - (cvmx_helper_interface_get_mode(interface) != - CVMX_HELPER_INTERFACE_MODE_SPI)) { - int i; - u8 *ptr = dev->dev_addr; - u64 mac = 0; - int index = INDEX(priv->port); - - for (i = 0; i < 6; i++) - mac = (mac << 8) | (u64)ptr[i]; - - gmx_cfg.u64 = - cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), - gmx_cfg.u64 & ~1ull); - - cvmx_write_csr(CVMX_GMXX_SMACX(index, interface), mac); - cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), - ptr[0]); - cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), - ptr[1]); - cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), - ptr[2]); - cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), - ptr[3]); - cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), - ptr[4]); - cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), - ptr[5]); - cvm_oct_common_set_multicast_list(dev); - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), - gmx_cfg.u64); - } - return 0; -} - -/** - * cvm_oct_common_set_mac_address - set the hardware MAC address for a device - * @dev: The device in question. - * @addr: Socket address. - * - * Returns Zero on success - */ -static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) -{ - int r = eth_mac_addr(dev, addr); - - if (r) - return r; - return cvm_oct_set_mac_filter(dev); -} - -/** - * cvm_oct_common_init - per network device initialization - * @dev: Device to initialize - * - * Returns Zero on success - */ -int cvm_oct_common_init(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - const u8 *mac = NULL; - - if (priv->of_node) - mac = of_get_mac_address(priv->of_node); - - if (!IS_ERR_OR_NULL(mac)) - ether_addr_copy(dev->dev_addr, mac); - else - eth_hw_addr_random(dev); - - /* - * Force the interface to use the POW send if always_use_pow - * was specified or it is in the pow send list. - */ - if ((pow_send_group != -1) && - (always_use_pow || strstr(pow_send_list, dev->name))) - priv->queue = -1; - - if (priv->queue != -1) - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - - /* We do our own locking, Linux doesn't need to */ - dev->features |= NETIF_F_LLTX; - dev->ethtool_ops = &cvm_oct_ethtool_ops; - - cvm_oct_set_mac_filter(dev); - dev_set_mtu(dev, dev->mtu); - - /* - * Zero out stats for port so we won't mistakenly show - * counters from the bootloader. - */ - memset(dev->netdev_ops->ndo_get_stats(dev), 0, - sizeof(struct net_device_stats)); - - if (dev->netdev_ops->ndo_stop) - dev->netdev_ops->ndo_stop(dev); - - return 0; -} - -void cvm_oct_common_uninit(struct net_device *dev) -{ - if (dev->phydev) - phy_disconnect(dev->phydev); -} - -int cvm_oct_common_open(struct net_device *dev, - void (*link_poll)(struct net_device *)) -{ - union cvmx_gmxx_prtx_cfg gmx_cfg; - struct octeon_ethernet *priv = netdev_priv(dev); - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - union cvmx_helper_link_info link_info; - int rv; - - rv = cvm_oct_phy_setup_device(dev); - if (rv) - return rv; - - gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); - gmx_cfg.s.en = 1; - if (octeon_has_feature(OCTEON_FEATURE_PKND)) - gmx_cfg.s.pknd = priv->port; - cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); - - if (octeon_is_simulation()) - return 0; - - if (dev->phydev) { - int r = phy_read_status(dev->phydev); - - if (r == 0 && dev->phydev->link == 0) - netif_carrier_off(dev); - cvm_oct_adjust_link(dev); - } else { - link_info = cvmx_helper_link_get(priv->port); - if (!link_info.s.link_up) - netif_carrier_off(dev); - priv->poll = link_poll; - link_poll(dev); - } - - return 0; -} - -void cvm_oct_link_poll(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - union cvmx_helper_link_info link_info; - - link_info = cvmx_helper_link_get(priv->port); - if (link_info.u64 == priv->link_info) - return; - - if (cvmx_helper_link_set(priv->port, link_info)) - link_info.u64 = priv->link_info; - else - priv->link_info = link_info.u64; - - if (link_info.s.link_up) { - if (!netif_carrier_ok(dev)) - netif_carrier_on(dev); - } else if (netif_carrier_ok(dev)) { - netif_carrier_off(dev); - } - cvm_oct_note_carrier(priv, link_info); -} - -static int cvm_oct_xaui_open(struct net_device *dev) -{ - return cvm_oct_common_open(dev, cvm_oct_link_poll); -} - -static const struct net_device_ops cvm_oct_npi_netdev_ops = { - .ndo_init = cvm_oct_common_init, - .ndo_uninit = cvm_oct_common_uninit, - .ndo_start_xmit = cvm_oct_xmit, - .ndo_set_rx_mode = cvm_oct_common_set_multicast_list, - .ndo_set_mac_address = cvm_oct_common_set_mac_address, - .ndo_do_ioctl = cvm_oct_ioctl, - .ndo_change_mtu = cvm_oct_common_change_mtu, - .ndo_get_stats = cvm_oct_common_get_stats, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = cvm_oct_poll_controller, -#endif -}; - -static const struct net_device_ops cvm_oct_xaui_netdev_ops = { - .ndo_init = cvm_oct_common_init, - .ndo_uninit = cvm_oct_common_uninit, - .ndo_open = cvm_oct_xaui_open, - .ndo_stop = cvm_oct_common_stop, - .ndo_start_xmit = cvm_oct_xmit, - .ndo_set_rx_mode = cvm_oct_common_set_multicast_list, - .ndo_set_mac_address = cvm_oct_common_set_mac_address, - .ndo_do_ioctl = cvm_oct_ioctl, - .ndo_change_mtu = cvm_oct_common_change_mtu, - .ndo_get_stats = cvm_oct_common_get_stats, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = cvm_oct_poll_controller, -#endif -}; - -static const struct net_device_ops cvm_oct_sgmii_netdev_ops = { - .ndo_init = cvm_oct_sgmii_init, - .ndo_uninit = cvm_oct_common_uninit, - .ndo_open = cvm_oct_sgmii_open, - .ndo_stop = cvm_oct_common_stop, - .ndo_start_xmit = cvm_oct_xmit, - .ndo_set_rx_mode = cvm_oct_common_set_multicast_list, - .ndo_set_mac_address = cvm_oct_common_set_mac_address, - .ndo_do_ioctl = cvm_oct_ioctl, - .ndo_change_mtu = cvm_oct_common_change_mtu, - .ndo_get_stats = cvm_oct_common_get_stats, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = cvm_oct_poll_controller, -#endif -}; - -static const struct net_device_ops cvm_oct_spi_netdev_ops = { - .ndo_init = cvm_oct_spi_init, - .ndo_uninit = cvm_oct_spi_uninit, - .ndo_start_xmit = cvm_oct_xmit, - .ndo_set_rx_mode = cvm_oct_common_set_multicast_list, - .ndo_set_mac_address = cvm_oct_common_set_mac_address, - .ndo_do_ioctl = cvm_oct_ioctl, - .ndo_change_mtu = cvm_oct_common_change_mtu, - .ndo_get_stats = cvm_oct_common_get_stats, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = cvm_oct_poll_controller, -#endif -}; - -static const struct net_device_ops cvm_oct_rgmii_netdev_ops = { - .ndo_init = cvm_oct_common_init, - .ndo_uninit = cvm_oct_common_uninit, - .ndo_open = cvm_oct_rgmii_open, - .ndo_stop = cvm_oct_common_stop, - .ndo_start_xmit = cvm_oct_xmit, - .ndo_set_rx_mode = cvm_oct_common_set_multicast_list, - .ndo_set_mac_address = cvm_oct_common_set_mac_address, - .ndo_do_ioctl = cvm_oct_ioctl, - .ndo_change_mtu = cvm_oct_common_change_mtu, - .ndo_get_stats = cvm_oct_common_get_stats, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = cvm_oct_poll_controller, -#endif -}; - -static const struct net_device_ops cvm_oct_pow_netdev_ops = { - .ndo_init = cvm_oct_common_init, - .ndo_start_xmit = cvm_oct_xmit_pow, - .ndo_set_rx_mode = cvm_oct_common_set_multicast_list, - .ndo_set_mac_address = cvm_oct_common_set_mac_address, - .ndo_do_ioctl = cvm_oct_ioctl, - .ndo_change_mtu = cvm_oct_common_change_mtu, - .ndo_get_stats = cvm_oct_common_get_stats, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = cvm_oct_poll_controller, -#endif -}; - -static struct device_node *cvm_oct_of_get_child - (const struct device_node *parent, int reg_val) -{ - struct device_node *node = NULL; - int size; - const __be32 *addr; - - for (;;) { - node = of_get_next_child(parent, node); - if (!node) - break; - addr = of_get_property(node, "reg", &size); - if (addr && (be32_to_cpu(*addr) == reg_val)) - break; - } - return node; -} - -static struct device_node *cvm_oct_node_for_port(struct device_node *pip, - int interface, int port) -{ - struct device_node *ni, *np; - - ni = cvm_oct_of_get_child(pip, interface); - if (!ni) - return NULL; - - np = cvm_oct_of_get_child(ni, port); - of_node_put(ni); - - return np; -} - -static void cvm_set_rgmii_delay(struct octeon_ethernet *priv, int iface, - int port) -{ - struct device_node *np = priv->of_node; - u32 delay_value; - bool rx_delay; - bool tx_delay; - - /* By default, both RX/TX delay is enabled in - * __cvmx_helper_rgmii_enable(). - */ - rx_delay = true; - tx_delay = true; - - if (!of_property_read_u32(np, "rx-delay", &delay_value)) { - cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, iface), delay_value); - rx_delay = delay_value > 0; - } - if (!of_property_read_u32(np, "tx-delay", &delay_value)) { - cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, iface), delay_value); - tx_delay = delay_value > 0; - } - - if (!rx_delay && !tx_delay) - priv->phy_mode = PHY_INTERFACE_MODE_RGMII_ID; - else if (!rx_delay) - priv->phy_mode = PHY_INTERFACE_MODE_RGMII_RXID; - else if (!tx_delay) - priv->phy_mode = PHY_INTERFACE_MODE_RGMII_TXID; - else - priv->phy_mode = PHY_INTERFACE_MODE_RGMII; -} - -static int cvm_oct_probe(struct platform_device *pdev) -{ - int num_interfaces; - int interface; - int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE; - int qos; - struct device_node *pip; - int mtu_overhead = ETH_HLEN + ETH_FCS_LEN; - -#if IS_ENABLED(CONFIG_VLAN_8021Q) - mtu_overhead += VLAN_HLEN; -#endif - - octeon_mdiobus_force_mod_depencency(); - - pip = pdev->dev.of_node; - if (!pip) { - pr_err("Error: No 'pip' in /aliases\n"); - return -EINVAL; - } - - cvm_oct_configure_common_hw(); - - cvmx_helper_initialize_packet_io_global(); - - if (receive_group_order) { - if (receive_group_order > 4) - receive_group_order = 4; - pow_receive_groups = (1 << (1 << receive_group_order)) - 1; - } else { - pow_receive_groups = BIT(pow_receive_group); - } - - /* Change the input group for all ports before input is enabled */ - num_interfaces = cvmx_helper_get_number_of_interfaces(); - for (interface = 0; interface < num_interfaces; interface++) { - int num_ports = cvmx_helper_ports_on_interface(interface); - int port; - - for (port = cvmx_helper_get_ipd_port(interface, 0); - port < cvmx_helper_get_ipd_port(interface, num_ports); - port++) { - union cvmx_pip_prt_tagx pip_prt_tagx; - - pip_prt_tagx.u64 = - cvmx_read_csr(CVMX_PIP_PRT_TAGX(port)); - - if (receive_group_order) { - int tag_mask; - - /* We support only 16 groups at the moment, so - * always disable the two additional "hidden" - * tag_mask bits on CN68XX. - */ - if (OCTEON_IS_MODEL(OCTEON_CN68XX)) - pip_prt_tagx.u64 |= 0x3ull << 44; - - tag_mask = ~((1 << receive_group_order) - 1); - pip_prt_tagx.s.grptagbase = 0; - pip_prt_tagx.s.grptagmask = tag_mask; - pip_prt_tagx.s.grptag = 1; - pip_prt_tagx.s.tag_mode = 0; - pip_prt_tagx.s.inc_prt_flag = 1; - pip_prt_tagx.s.ip6_dprt_flag = 1; - pip_prt_tagx.s.ip4_dprt_flag = 1; - pip_prt_tagx.s.ip6_sprt_flag = 1; - pip_prt_tagx.s.ip4_sprt_flag = 1; - pip_prt_tagx.s.ip6_dst_flag = 1; - pip_prt_tagx.s.ip4_dst_flag = 1; - pip_prt_tagx.s.ip6_src_flag = 1; - pip_prt_tagx.s.ip4_src_flag = 1; - pip_prt_tagx.s.grp = 0; - } else { - pip_prt_tagx.s.grptag = 0; - pip_prt_tagx.s.grp = pow_receive_group; - } - - cvmx_write_csr(CVMX_PIP_PRT_TAGX(port), - pip_prt_tagx.u64); - } - } - - cvmx_helper_ipd_and_packet_input_enable(); - - memset(cvm_oct_device, 0, sizeof(cvm_oct_device)); - - /* - * Initialize the FAU used for counting packet buffers that - * need to be freed. - */ - cvmx_fau_atomic_write32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); - - /* Initialize the FAU used for counting tx SKBs that need to be freed */ - cvmx_fau_atomic_write32(FAU_TOTAL_TX_TO_CLEAN, 0); - - if ((pow_send_group != -1)) { - struct net_device *dev; - - dev = alloc_etherdev(sizeof(struct octeon_ethernet)); - if (dev) { - /* Initialize the device private structure. */ - struct octeon_ethernet *priv = netdev_priv(dev); - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &cvm_oct_pow_netdev_ops; - priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED; - priv->port = CVMX_PIP_NUM_INPUT_PORTS; - priv->queue = -1; - strscpy(dev->name, "pow%d", sizeof(dev->name)); - for (qos = 0; qos < 16; qos++) - skb_queue_head_init(&priv->tx_free_list[qos]); - dev->min_mtu = VLAN_ETH_ZLEN - mtu_overhead; - dev->max_mtu = OCTEON_MAX_MTU - mtu_overhead; - - if (register_netdev(dev) < 0) { - pr_err("Failed to register ethernet device for POW\n"); - free_netdev(dev); - } else { - cvm_oct_device[CVMX_PIP_NUM_INPUT_PORTS] = dev; - pr_info("%s: POW send group %d, receive group %d\n", - dev->name, pow_send_group, - pow_receive_group); - } - } else { - pr_err("Failed to allocate ethernet device for POW\n"); - } - } - - num_interfaces = cvmx_helper_get_number_of_interfaces(); - for (interface = 0; interface < num_interfaces; interface++) { - cvmx_helper_interface_mode_t imode = - cvmx_helper_interface_get_mode(interface); - int num_ports = cvmx_helper_ports_on_interface(interface); - int port; - int port_index; - - for (port_index = 0, - port = cvmx_helper_get_ipd_port(interface, 0); - port < cvmx_helper_get_ipd_port(interface, num_ports); - port_index++, port++) { - struct octeon_ethernet *priv; - struct net_device *dev = - alloc_etherdev(sizeof(struct octeon_ethernet)); - if (!dev) { - pr_err("Failed to allocate ethernet device for port %d\n", - port); - continue; - } - - /* Initialize the device private structure. */ - SET_NETDEV_DEV(dev, &pdev->dev); - priv = netdev_priv(dev); - priv->netdev = dev; - priv->of_node = cvm_oct_node_for_port(pip, interface, - port_index); - - INIT_DELAYED_WORK(&priv->port_periodic_work, - cvm_oct_periodic_worker); - priv->imode = imode; - priv->port = port; - priv->queue = cvmx_pko_get_base_queue(priv->port); - priv->fau = fau - cvmx_pko_get_num_queues(port) * 4; - priv->phy_mode = PHY_INTERFACE_MODE_NA; - for (qos = 0; qos < 16; qos++) - skb_queue_head_init(&priv->tx_free_list[qos]); - for (qos = 0; qos < cvmx_pko_get_num_queues(port); - qos++) - cvmx_fau_atomic_write32(priv->fau + qos * 4, 0); - dev->min_mtu = VLAN_ETH_ZLEN - mtu_overhead; - dev->max_mtu = OCTEON_MAX_MTU - mtu_overhead; - - switch (priv->imode) { - /* These types don't support ports to IPD/PKO */ - case CVMX_HELPER_INTERFACE_MODE_DISABLED: - case CVMX_HELPER_INTERFACE_MODE_PCIE: - case CVMX_HELPER_INTERFACE_MODE_PICMG: - break; - - case CVMX_HELPER_INTERFACE_MODE_NPI: - dev->netdev_ops = &cvm_oct_npi_netdev_ops; - strscpy(dev->name, "npi%d", sizeof(dev->name)); - break; - - case CVMX_HELPER_INTERFACE_MODE_XAUI: - dev->netdev_ops = &cvm_oct_xaui_netdev_ops; - strscpy(dev->name, "xaui%d", sizeof(dev->name)); - break; - - case CVMX_HELPER_INTERFACE_MODE_LOOP: - dev->netdev_ops = &cvm_oct_npi_netdev_ops; - strscpy(dev->name, "loop%d", sizeof(dev->name)); - break; - - case CVMX_HELPER_INTERFACE_MODE_SGMII: - priv->phy_mode = PHY_INTERFACE_MODE_SGMII; - dev->netdev_ops = &cvm_oct_sgmii_netdev_ops; - strscpy(dev->name, "eth%d", sizeof(dev->name)); - break; - - case CVMX_HELPER_INTERFACE_MODE_SPI: - dev->netdev_ops = &cvm_oct_spi_netdev_ops; - strscpy(dev->name, "spi%d", sizeof(dev->name)); - break; - - case CVMX_HELPER_INTERFACE_MODE_GMII: - priv->phy_mode = PHY_INTERFACE_MODE_GMII; - dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; - strscpy(dev->name, "eth%d", sizeof(dev->name)); - break; - - case CVMX_HELPER_INTERFACE_MODE_RGMII: - dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; - strscpy(dev->name, "eth%d", sizeof(dev->name)); - cvm_set_rgmii_delay(priv, interface, - port_index); - break; - } - - if (!dev->netdev_ops) { - free_netdev(dev); - } else if (register_netdev(dev) < 0) { - pr_err("Failed to register ethernet device for interface %d, port %d\n", - interface, priv->port); - free_netdev(dev); - } else { - cvm_oct_device[priv->port] = dev; - fau -= - cvmx_pko_get_num_queues(priv->port) * - sizeof(u32); - schedule_delayed_work(&priv->port_periodic_work, - HZ); - } - } - } - - cvm_oct_tx_initialize(); - cvm_oct_rx_initialize(); - - /* - * 150 uS: about 10 1500-byte packets at 1GE. - */ - cvm_oct_tx_poll_interval = 150 * (octeon_get_clock_rate() / 1000000); - - schedule_delayed_work(&cvm_oct_rx_refill_work, HZ); - - return 0; -} - -static int cvm_oct_remove(struct platform_device *pdev) -{ - int port; - - cvmx_ipd_disable(); - - atomic_inc_return(&cvm_oct_poll_queue_stopping); - cancel_delayed_work_sync(&cvm_oct_rx_refill_work); - - cvm_oct_rx_shutdown(); - cvm_oct_tx_shutdown(); - - cvmx_pko_disable(); - - /* Free the ethernet devices */ - for (port = 0; port < TOTAL_NUMBER_OF_PORTS; port++) { - if (cvm_oct_device[port]) { - struct net_device *dev = cvm_oct_device[port]; - struct octeon_ethernet *priv = netdev_priv(dev); - - cancel_delayed_work_sync(&priv->port_periodic_work); - - cvm_oct_tx_shutdown_dev(dev); - unregister_netdev(dev); - free_netdev(dev); - cvm_oct_device[port] = NULL; - } - } - - cvmx_pko_shutdown(); - - cvmx_ipd_free_ptr(); - - /* Free the HW pools */ - cvm_oct_mem_empty_fpa(CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE, - num_packet_buffers); - cvm_oct_mem_empty_fpa(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE, - num_packet_buffers); - if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL) - cvm_oct_mem_empty_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL, - CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128); - return 0; -} - -static const struct of_device_id cvm_oct_match[] = { - { - .compatible = "cavium,octeon-3860-pip", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, cvm_oct_match); - -static struct platform_driver cvm_oct_driver = { - .probe = cvm_oct_probe, - .remove = cvm_oct_remove, - .driver = { - .name = KBUILD_MODNAME, - .of_match_table = cvm_oct_match, - }, -}; - -module_platform_driver(cvm_oct_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Cavium Networks "); -MODULE_DESCRIPTION("Cavium Networks Octeon ethernet driver."); diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h deleted file mode 100644 index a6140705706f..000000000000 --- a/drivers/staging/octeon/octeon-ethernet.h +++ /dev/null @@ -1,107 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * This file is based on code from OCTEON SDK by Cavium Networks. - * - * Copyright (c) 2003-2010 Cavium Networks - */ - -/* - * External interface for the Cavium Octeon ethernet driver. - */ -#ifndef OCTEON_ETHERNET_H -#define OCTEON_ETHERNET_H - -#include -#include - -#ifdef CONFIG_CAVIUM_OCTEON_SOC - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#else - -#include "octeon-stubs.h" - -#endif - -/** - * This is the definition of the Ethernet driver's private - * driver state stored in netdev_priv(dev). - */ -struct octeon_ethernet { - /* PKO hardware output port */ - int port; - /* PKO hardware queue for the port */ - int queue; - /* Hardware fetch and add to count outstanding tx buffers */ - int fau; - /* My netdev. */ - struct net_device *netdev; - /* - * Type of port. This is one of the enums in - * cvmx_helper_interface_mode_t - */ - int imode; - /* PHY mode */ - phy_interface_t phy_mode; - /* List of outstanding tx buffers per queue */ - struct sk_buff_head tx_free_list[16]; - unsigned int last_speed; - unsigned int last_link; - /* Last negotiated link state */ - u64 link_info; - /* Called periodically to check link status */ - void (*poll)(struct net_device *dev); - struct delayed_work port_periodic_work; - struct device_node *of_node; -}; - -int cvm_oct_free_work(void *work_queue_entry); - -int cvm_oct_rgmii_open(struct net_device *dev); - -int cvm_oct_sgmii_init(struct net_device *dev); -int cvm_oct_sgmii_open(struct net_device *dev); - -int cvm_oct_spi_init(struct net_device *dev); -void cvm_oct_spi_uninit(struct net_device *dev); - -int cvm_oct_common_init(struct net_device *dev); -void cvm_oct_common_uninit(struct net_device *dev); -void cvm_oct_adjust_link(struct net_device *dev); -int cvm_oct_common_stop(struct net_device *dev); -int cvm_oct_common_open(struct net_device *dev, - void (*link_poll)(struct net_device *)); -void cvm_oct_note_carrier(struct octeon_ethernet *priv, - union cvmx_helper_link_info li); -void cvm_oct_link_poll(struct net_device *dev); - -extern int always_use_pow; -extern int pow_send_group; -extern int pow_receive_groups; -extern char pow_send_list[]; -extern struct net_device *cvm_oct_device[]; -extern atomic_t cvm_oct_poll_queue_stopping; -extern u64 cvm_oct_tx_poll_interval; - -extern int rx_napi_weight; - -#endif diff --git a/drivers/staging/octeon/octeon-stubs.h b/drivers/staging/octeon/octeon-stubs.h deleted file mode 100644 index 79213c045504..000000000000 --- a/drivers/staging/octeon/octeon-stubs.h +++ /dev/null @@ -1,1433 +0,0 @@ -#define CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE 512 - -#ifndef XKPHYS_TO_PHYS -# define XKPHYS_TO_PHYS(p) (p) -#endif - -#define OCTEON_IRQ_WORKQ0 0 -#define OCTEON_IRQ_RML 0 -#define OCTEON_IRQ_TIMER1 0 -#define OCTEON_IS_MODEL(x) 0 -#define octeon_has_feature(x) 0 -#define octeon_get_clock_rate() 0 - -#define CVMX_SYNCIOBDMA do { } while(0) - -#define CVMX_HELPER_INPUT_TAG_TYPE 0 -#define CVMX_HELPER_FIRST_MBUFF_SKIP 7 -#define CVMX_FAU_REG_END (2048) -#define CVMX_FPA_OUTPUT_BUFFER_POOL (2) -#define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE 16 -#define CVMX_FPA_PACKET_POOL (0) -#define CVMX_FPA_PACKET_POOL_SIZE 16 -#define CVMX_FPA_WQE_POOL (1) -#define CVMX_FPA_WQE_POOL_SIZE 16 -#define CVMX_GMXX_RXX_ADR_CAM_EN(a, b) ((a)+(b)) -#define CVMX_GMXX_RXX_ADR_CTL(a, b) ((a)+(b)) -#define CVMX_GMXX_PRTX_CFG(a, b) ((a)+(b)) -#define CVMX_GMXX_RXX_FRM_MAX(a, b) ((a)+(b)) -#define CVMX_GMXX_RXX_JABBER(a, b) ((a)+(b)) -#define CVMX_IPD_CTL_STATUS 0 -#define CVMX_PIP_FRM_LEN_CHKX(a) (a) -#define CVMX_PIP_NUM_INPUT_PORTS 1 -#define CVMX_SCR_SCRATCH 0 -#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE0 2 -#define CVMX_PKO_QUEUES_PER_PORT_INTERFACE1 2 -#define CVMX_IPD_SUB_PORT_FCS 0 -#define CVMX_SSO_WQ_IQ_DIS 0 -#define CVMX_SSO_WQ_INT 0 -#define CVMX_POW_WQ_INT 0 -#define CVMX_SSO_WQ_INT_PC 0 -#define CVMX_NPI_RSL_INT_BLOCKS 0 -#define CVMX_POW_WQ_INT_PC 0 - -union cvmx_pip_wqe_word2 { - uint64_t u64; - struct { - uint64_t bufs:8; - uint64_t ip_offset:8; - uint64_t vlan_valid:1; - uint64_t vlan_stacked:1; - uint64_t unassigned:1; - uint64_t vlan_cfi:1; - uint64_t vlan_id:12; - uint64_t pr:4; - uint64_t unassigned2:8; - uint64_t dec_ipcomp:1; - uint64_t tcp_or_udp:1; - uint64_t dec_ipsec:1; - uint64_t is_v6:1; - uint64_t software:1; - uint64_t L4_error:1; - uint64_t is_frag:1; - uint64_t IP_exc:1; - uint64_t is_bcast:1; - uint64_t is_mcast:1; - uint64_t not_IP:1; - uint64_t rcv_error:1; - uint64_t err_code:8; - } s; - struct { - uint64_t bufs:8; - uint64_t ip_offset:8; - uint64_t vlan_valid:1; - uint64_t vlan_stacked:1; - uint64_t unassigned:1; - uint64_t vlan_cfi:1; - uint64_t vlan_id:12; - uint64_t port:12; - uint64_t dec_ipcomp:1; - uint64_t tcp_or_udp:1; - uint64_t dec_ipsec:1; - uint64_t is_v6:1; - uint64_t software:1; - uint64_t L4_error:1; - uint64_t is_frag:1; - uint64_t IP_exc:1; - uint64_t is_bcast:1; - uint64_t is_mcast:1; - uint64_t not_IP:1; - uint64_t rcv_error:1; - uint64_t err_code:8; - } s_cn68xx; - - struct { - uint64_t unused1:16; - uint64_t vlan:16; - uint64_t unused2:32; - } svlan; - struct { - uint64_t bufs:8; - uint64_t unused:8; - uint64_t vlan_valid:1; - uint64_t vlan_stacked:1; - uint64_t unassigned:1; - uint64_t vlan_cfi:1; - uint64_t vlan_id:12; - uint64_t pr:4; - uint64_t unassigned2:12; - uint64_t software:1; - uint64_t unassigned3:1; - uint64_t is_rarp:1; - uint64_t is_arp:1; - uint64_t is_bcast:1; - uint64_t is_mcast:1; - uint64_t not_IP:1; - uint64_t rcv_error:1; - uint64_t err_code:8; - } snoip; - -}; - -union cvmx_pip_wqe_word0 { - struct { - uint64_t next_ptr:40; - uint8_t unused; - __wsum hw_chksum; - } cn38xx; - struct { - uint64_t pknd:6; /* 0..5 */ - uint64_t unused2:2; /* 6..7 */ - uint64_t bpid:6; /* 8..13 */ - uint64_t unused1:18; /* 14..31 */ - uint64_t l2ptr:8; /* 32..39 */ - uint64_t l3ptr:8; /* 40..47 */ - uint64_t unused0:8; /* 48..55 */ - uint64_t l4ptr:8; /* 56..63 */ - } cn68xx; -}; - -union cvmx_wqe_word0 { - uint64_t u64; - union cvmx_pip_wqe_word0 pip; -}; - -union cvmx_wqe_word1 { - uint64_t u64; - struct { - uint64_t tag:32; - uint64_t tag_type:2; - uint64_t varies:14; - uint64_t len:16; - }; - struct { - uint64_t tag:32; - uint64_t tag_type:2; - uint64_t zero_2:3; - uint64_t grp:6; - uint64_t zero_1:1; - uint64_t qos:3; - uint64_t zero_0:1; - uint64_t len:16; - } cn68xx; - struct { - uint64_t tag:32; - uint64_t tag_type:2; - uint64_t zero_2:1; - uint64_t grp:4; - uint64_t qos:3; - uint64_t ipprt:6; - uint64_t len:16; - } cn38xx; -}; - -union cvmx_buf_ptr { - void *ptr; - uint64_t u64; - struct { - uint64_t i:1; - uint64_t back:4; - uint64_t pool:3; - uint64_t size:16; - uint64_t addr:40; - } s; -}; - -struct cvmx_wqe { - union cvmx_wqe_word0 word0; - union cvmx_wqe_word1 word1; - union cvmx_pip_wqe_word2 word2; - union cvmx_buf_ptr packet_ptr; - uint8_t packet_data[96]; -}; - -union cvmx_helper_link_info { - uint64_t u64; - struct { - uint64_t reserved_20_63:44; - uint64_t link_up:1; /**< Is the physical link up? */ - uint64_t full_duplex:1; /**< 1 if the link is full duplex */ - uint64_t speed:18; /**< Speed of the link in Mbps */ - } s; -}; - -enum cvmx_fau_reg_32 { - CVMX_FAU_REG_32_START = 0, -}; - -enum cvmx_fau_op_size { - CVMX_FAU_OP_SIZE_8 = 0, - CVMX_FAU_OP_SIZE_16 = 1, - CVMX_FAU_OP_SIZE_32 = 2, - CVMX_FAU_OP_SIZE_64 = 3 -}; - -typedef enum { - CVMX_SPI_MODE_UNKNOWN = 0, - CVMX_SPI_MODE_TX_HALFPLEX = 1, - CVMX_SPI_MODE_RX_HALFPLEX = 2, - CVMX_SPI_MODE_DUPLEX = 3 -} cvmx_spi_mode_t; - -typedef enum { - CVMX_HELPER_INTERFACE_MODE_DISABLED, - CVMX_HELPER_INTERFACE_MODE_RGMII, - CVMX_HELPER_INTERFACE_MODE_GMII, - CVMX_HELPER_INTERFACE_MODE_SPI, - CVMX_HELPER_INTERFACE_MODE_PCIE, - CVMX_HELPER_INTERFACE_MODE_XAUI, - CVMX_HELPER_INTERFACE_MODE_SGMII, - CVMX_HELPER_INTERFACE_MODE_PICMG, - CVMX_HELPER_INTERFACE_MODE_NPI, - CVMX_HELPER_INTERFACE_MODE_LOOP, -} cvmx_helper_interface_mode_t; - -typedef enum { - CVMX_POW_WAIT = 1, - CVMX_POW_NO_WAIT = 0, -} cvmx_pow_wait_t; - -typedef enum { - CVMX_PKO_LOCK_NONE = 0, - CVMX_PKO_LOCK_ATOMIC_TAG = 1, - CVMX_PKO_LOCK_CMD_QUEUE = 2, -} cvmx_pko_lock_t; - -typedef enum { - CVMX_PKO_SUCCESS, - CVMX_PKO_INVALID_PORT, - CVMX_PKO_INVALID_QUEUE, - CVMX_PKO_INVALID_PRIORITY, - CVMX_PKO_NO_MEMORY, - CVMX_PKO_PORT_ALREADY_SETUP, - CVMX_PKO_CMD_QUEUE_INIT_ERROR -} cvmx_pko_status_t; - -enum cvmx_pow_tag_type { - CVMX_POW_TAG_TYPE_ORDERED = 0L, - CVMX_POW_TAG_TYPE_ATOMIC = 1L, - CVMX_POW_TAG_TYPE_NULL = 2L, - CVMX_POW_TAG_TYPE_NULL_NULL = 3L -}; - -union cvmx_ipd_ctl_status { - uint64_t u64; - struct cvmx_ipd_ctl_status_s { - uint64_t reserved_18_63:46; - uint64_t use_sop:1; - uint64_t rst_done:1; - uint64_t clken:1; - uint64_t no_wptr:1; - uint64_t pq_apkt:1; - uint64_t pq_nabuf:1; - uint64_t ipd_full:1; - uint64_t pkt_off:1; - uint64_t len_m8:1; - uint64_t reset:1; - uint64_t addpkt:1; - uint64_t naddbuf:1; - uint64_t pkt_lend:1; - uint64_t wqe_lend:1; - uint64_t pbp_en:1; - uint64_t opc_mode:2; - uint64_t ipd_en:1; - } s; - struct cvmx_ipd_ctl_status_cn30xx { - uint64_t reserved_10_63:54; - uint64_t len_m8:1; - uint64_t reset:1; - uint64_t addpkt:1; - uint64_t naddbuf:1; - uint64_t pkt_lend:1; - uint64_t wqe_lend:1; - uint64_t pbp_en:1; - uint64_t opc_mode:2; - uint64_t ipd_en:1; - } cn30xx; - struct cvmx_ipd_ctl_status_cn38xxp2 { - uint64_t reserved_9_63:55; - uint64_t reset:1; - uint64_t addpkt:1; - uint64_t naddbuf:1; - uint64_t pkt_lend:1; - uint64_t wqe_lend:1; - uint64_t pbp_en:1; - uint64_t opc_mode:2; - uint64_t ipd_en:1; - } cn38xxp2; - struct cvmx_ipd_ctl_status_cn50xx { - uint64_t reserved_15_63:49; - uint64_t no_wptr:1; - uint64_t pq_apkt:1; - uint64_t pq_nabuf:1; - uint64_t ipd_full:1; - uint64_t pkt_off:1; - uint64_t len_m8:1; - uint64_t reset:1; - uint64_t addpkt:1; - uint64_t naddbuf:1; - uint64_t pkt_lend:1; - uint64_t wqe_lend:1; - uint64_t pbp_en:1; - uint64_t opc_mode:2; - uint64_t ipd_en:1; - } cn50xx; - struct cvmx_ipd_ctl_status_cn58xx { - uint64_t reserved_12_63:52; - uint64_t ipd_full:1; - uint64_t pkt_off:1; - uint64_t len_m8:1; - uint64_t reset:1; - uint64_t addpkt:1; - uint64_t naddbuf:1; - uint64_t pkt_lend:1; - uint64_t wqe_lend:1; - uint64_t pbp_en:1; - uint64_t opc_mode:2; - uint64_t ipd_en:1; - } cn58xx; - struct cvmx_ipd_ctl_status_cn63xxp1 { - uint64_t reserved_16_63:48; - uint64_t clken:1; - uint64_t no_wptr:1; - uint64_t pq_apkt:1; - uint64_t pq_nabuf:1; - uint64_t ipd_full:1; - uint64_t pkt_off:1; - uint64_t len_m8:1; - uint64_t reset:1; - uint64_t addpkt:1; - uint64_t naddbuf:1; - uint64_t pkt_lend:1; - uint64_t wqe_lend:1; - uint64_t pbp_en:1; - uint64_t opc_mode:2; - uint64_t ipd_en:1; - } cn63xxp1; -}; - -union cvmx_ipd_sub_port_fcs { - uint64_t u64; - struct cvmx_ipd_sub_port_fcs_s { - uint64_t port_bit:32; - uint64_t reserved_32_35:4; - uint64_t port_bit2:4; - uint64_t reserved_40_63:24; - } s; - struct cvmx_ipd_sub_port_fcs_cn30xx { - uint64_t port_bit:3; - uint64_t reserved_3_63:61; - } cn30xx; - struct cvmx_ipd_sub_port_fcs_cn38xx { - uint64_t port_bit:32; - uint64_t reserved_32_63:32; - } cn38xx; -}; - -union cvmx_ipd_sub_port_qos_cnt { - uint64_t u64; - struct cvmx_ipd_sub_port_qos_cnt_s { - uint64_t cnt:32; - uint64_t port_qos:9; - uint64_t reserved_41_63:23; - } s; -}; -typedef struct { - uint32_t dropped_octets; - uint32_t dropped_packets; - uint32_t pci_raw_packets; - uint32_t octets; - uint32_t packets; - uint32_t multicast_packets; - uint32_t broadcast_packets; - uint32_t len_64_packets; - uint32_t len_65_127_packets; - uint32_t len_128_255_packets; - uint32_t len_256_511_packets; - uint32_t len_512_1023_packets; - uint32_t len_1024_1518_packets; - uint32_t len_1519_max_packets; - uint32_t fcs_align_err_packets; - uint32_t runt_packets; - uint32_t runt_crc_packets; - uint32_t oversize_packets; - uint32_t oversize_crc_packets; - uint32_t inb_packets; - uint64_t inb_octets; - uint16_t inb_errors; -} cvmx_pip_port_status_t; - -typedef struct { - uint32_t packets; - uint64_t octets; - uint64_t doorbell; -} cvmx_pko_port_status_t; - -union cvmx_pip_frm_len_chkx { - uint64_t u64; - struct cvmx_pip_frm_len_chkx_s { - uint64_t reserved_32_63:32; - uint64_t maxlen:16; - uint64_t minlen:16; - } s; -}; - -union cvmx_gmxx_rxx_frm_ctl { - uint64_t u64; - struct cvmx_gmxx_rxx_frm_ctl_s { - uint64_t pre_chk:1; - uint64_t pre_strp:1; - uint64_t ctl_drp:1; - uint64_t ctl_bck:1; - uint64_t ctl_mcst:1; - uint64_t ctl_smac:1; - uint64_t pre_free:1; - uint64_t vlan_len:1; - uint64_t pad_len:1; - uint64_t pre_align:1; - uint64_t null_dis:1; - uint64_t reserved_11_11:1; - uint64_t ptp_mode:1; - uint64_t reserved_13_63:51; - } s; - struct cvmx_gmxx_rxx_frm_ctl_cn30xx { - uint64_t pre_chk:1; - uint64_t pre_strp:1; - uint64_t ctl_drp:1; - uint64_t ctl_bck:1; - uint64_t ctl_mcst:1; - uint64_t ctl_smac:1; - uint64_t pre_free:1; - uint64_t vlan_len:1; - uint64_t pad_len:1; - uint64_t reserved_9_63:55; - } cn30xx; - struct cvmx_gmxx_rxx_frm_ctl_cn31xx { - uint64_t pre_chk:1; - uint64_t pre_strp:1; - uint64_t ctl_drp:1; - uint64_t ctl_bck:1; - uint64_t ctl_mcst:1; - uint64_t ctl_smac:1; - uint64_t pre_free:1; - uint64_t vlan_len:1; - uint64_t reserved_8_63:56; - } cn31xx; - struct cvmx_gmxx_rxx_frm_ctl_cn50xx { - uint64_t pre_chk:1; - uint64_t pre_strp:1; - uint64_t ctl_drp:1; - uint64_t ctl_bck:1; - uint64_t ctl_mcst:1; - uint64_t ctl_smac:1; - uint64_t pre_free:1; - uint64_t reserved_7_8:2; - uint64_t pre_align:1; - uint64_t null_dis:1; - uint64_t reserved_11_63:53; - } cn50xx; - struct cvmx_gmxx_rxx_frm_ctl_cn56xxp1 { - uint64_t pre_chk:1; - uint64_t pre_strp:1; - uint64_t ctl_drp:1; - uint64_t ctl_bck:1; - uint64_t ctl_mcst:1; - uint64_t ctl_smac:1; - uint64_t pre_free:1; - uint64_t reserved_7_8:2; - uint64_t pre_align:1; - uint64_t reserved_10_63:54; - } cn56xxp1; - struct cvmx_gmxx_rxx_frm_ctl_cn58xx { - uint64_t pre_chk:1; - uint64_t pre_strp:1; - uint64_t ctl_drp:1; - uint64_t ctl_bck:1; - uint64_t ctl_mcst:1; - uint64_t ctl_smac:1; - uint64_t pre_free:1; - uint64_t vlan_len:1; - uint64_t pad_len:1; - uint64_t pre_align:1; - uint64_t null_dis:1; - uint64_t reserved_11_63:53; - } cn58xx; - struct cvmx_gmxx_rxx_frm_ctl_cn61xx { - uint64_t pre_chk:1; - uint64_t pre_strp:1; - uint64_t ctl_drp:1; - uint64_t ctl_bck:1; - uint64_t ctl_mcst:1; - uint64_t ctl_smac:1; - uint64_t pre_free:1; - uint64_t reserved_7_8:2; - uint64_t pre_align:1; - uint64_t null_dis:1; - uint64_t reserved_11_11:1; - uint64_t ptp_mode:1; - uint64_t reserved_13_63:51; - } cn61xx; -}; - -union cvmx_gmxx_rxx_int_reg { - uint64_t u64; - struct cvmx_gmxx_rxx_int_reg_s { - uint64_t minerr:1; - uint64_t carext:1; - uint64_t maxerr:1; - uint64_t jabber:1; - uint64_t fcserr:1; - uint64_t alnerr:1; - uint64_t lenerr:1; - uint64_t rcverr:1; - uint64_t skperr:1; - uint64_t niberr:1; - uint64_t ovrerr:1; - uint64_t pcterr:1; - uint64_t rsverr:1; - uint64_t falerr:1; - uint64_t coldet:1; - uint64_t ifgerr:1; - uint64_t phy_link:1; - uint64_t phy_spd:1; - uint64_t phy_dupx:1; - uint64_t pause_drp:1; - uint64_t loc_fault:1; - uint64_t rem_fault:1; - uint64_t bad_seq:1; - uint64_t bad_term:1; - uint64_t unsop:1; - uint64_t uneop:1; - uint64_t undat:1; - uint64_t hg2fld:1; - uint64_t hg2cc:1; - uint64_t reserved_29_63:35; - } s; - struct cvmx_gmxx_rxx_int_reg_cn30xx { - uint64_t minerr:1; - uint64_t carext:1; - uint64_t maxerr:1; - uint64_t jabber:1; - uint64_t fcserr:1; - uint64_t alnerr:1; - uint64_t lenerr:1; - uint64_t rcverr:1; - uint64_t skperr:1; - uint64_t niberr:1; - uint64_t ovrerr:1; - uint64_t pcterr:1; - uint64_t rsverr:1; - uint64_t falerr:1; - uint64_t coldet:1; - uint64_t ifgerr:1; - uint64_t phy_link:1; - uint64_t phy_spd:1; - uint64_t phy_dupx:1; - uint64_t reserved_19_63:45; - } cn30xx; - struct cvmx_gmxx_rxx_int_reg_cn50xx { - uint64_t reserved_0_0:1; - uint64_t carext:1; - uint64_t reserved_2_2:1; - uint64_t jabber:1; - uint64_t fcserr:1; - uint64_t alnerr:1; - uint64_t reserved_6_6:1; - uint64_t rcverr:1; - uint64_t skperr:1; - uint64_t niberr:1; - uint64_t ovrerr:1; - uint64_t pcterr:1; - uint64_t rsverr:1; - uint64_t falerr:1; - uint64_t coldet:1; - uint64_t ifgerr:1; - uint64_t phy_link:1; - uint64_t phy_spd:1; - uint64_t phy_dupx:1; - uint64_t pause_drp:1; - uint64_t reserved_20_63:44; - } cn50xx; - struct cvmx_gmxx_rxx_int_reg_cn52xx { - uint64_t reserved_0_0:1; - uint64_t carext:1; - uint64_t reserved_2_2:1; - uint64_t jabber:1; - uint64_t fcserr:1; - uint64_t reserved_5_6:2; - uint64_t rcverr:1; - uint64_t skperr:1; - uint64_t reserved_9_9:1; - uint64_t ovrerr:1; - uint64_t pcterr:1; - uint64_t rsverr:1; - uint64_t falerr:1; - uint64_t coldet:1; - uint64_t ifgerr:1; - uint64_t reserved_16_18:3; - uint64_t pause_drp:1; - uint64_t loc_fault:1; - uint64_t rem_fault:1; - uint64_t bad_seq:1; - uint64_t bad_term:1; - uint64_t unsop:1; - uint64_t uneop:1; - uint64_t undat:1; - uint64_t hg2fld:1; - uint64_t hg2cc:1; - uint64_t reserved_29_63:35; - } cn52xx; - struct cvmx_gmxx_rxx_int_reg_cn56xxp1 { - uint64_t reserved_0_0:1; - uint64_t carext:1; - uint64_t reserved_2_2:1; - uint64_t jabber:1; - uint64_t fcserr:1; - uint64_t reserved_5_6:2; - uint64_t rcverr:1; - uint64_t skperr:1; - uint64_t reserved_9_9:1; - uint64_t ovrerr:1; - uint64_t pcterr:1; - uint64_t rsverr:1; - uint64_t falerr:1; - uint64_t coldet:1; - uint64_t ifgerr:1; - uint64_t reserved_16_18:3; - uint64_t pause_drp:1; - uint64_t loc_fault:1; - uint64_t rem_fault:1; - uint64_t bad_seq:1; - uint64_t bad_term:1; - uint64_t unsop:1; - uint64_t uneop:1; - uint64_t undat:1; - uint64_t reserved_27_63:37; - } cn56xxp1; - struct cvmx_gmxx_rxx_int_reg_cn58xx { - uint64_t minerr:1; - uint64_t carext:1; - uint64_t maxerr:1; - uint64_t jabber:1; - uint64_t fcserr:1; - uint64_t alnerr:1; - uint64_t lenerr:1; - uint64_t rcverr:1; - uint64_t skperr:1; - uint64_t niberr:1; - uint64_t ovrerr:1; - uint64_t pcterr:1; - uint64_t rsverr:1; - uint64_t falerr:1; - uint64_t coldet:1; - uint64_t ifgerr:1; - uint64_t phy_link:1; - uint64_t phy_spd:1; - uint64_t phy_dupx:1; - uint64_t pause_drp:1; - uint64_t reserved_20_63:44; - } cn58xx; - struct cvmx_gmxx_rxx_int_reg_cn61xx { - uint64_t minerr:1; - uint64_t carext:1; - uint64_t reserved_2_2:1; - uint64_t jabber:1; - uint64_t fcserr:1; - uint64_t reserved_5_6:2; - uint64_t rcverr:1; - uint64_t skperr:1; - uint64_t reserved_9_9:1; - uint64_t ovrerr:1; - uint64_t pcterr:1; - uint64_t rsverr:1; - uint64_t falerr:1; - uint64_t coldet:1; - uint64_t ifgerr:1; - uint64_t reserved_16_18:3; - uint64_t pause_drp:1; - uint64_t loc_fault:1; - uint64_t rem_fault:1; - uint64_t bad_seq:1; - uint64_t bad_term:1; - uint64_t unsop:1; - uint64_t uneop:1; - uint64_t undat:1; - uint64_t hg2fld:1; - uint64_t hg2cc:1; - uint64_t reserved_29_63:35; - } cn61xx; -}; - -union cvmx_gmxx_prtx_cfg { - uint64_t u64; - struct cvmx_gmxx_prtx_cfg_s { - uint64_t reserved_22_63:42; - uint64_t pknd:6; - uint64_t reserved_14_15:2; - uint64_t tx_idle:1; - uint64_t rx_idle:1; - uint64_t reserved_9_11:3; - uint64_t speed_msb:1; - uint64_t reserved_4_7:4; - uint64_t slottime:1; - uint64_t duplex:1; - uint64_t speed:1; - uint64_t en:1; - } s; - struct cvmx_gmxx_prtx_cfg_cn30xx { - uint64_t reserved_4_63:60; - uint64_t slottime:1; - uint64_t duplex:1; - uint64_t speed:1; - uint64_t en:1; - } cn30xx; - struct cvmx_gmxx_prtx_cfg_cn52xx { - uint64_t reserved_14_63:50; - uint64_t tx_idle:1; - uint64_t rx_idle:1; - uint64_t reserved_9_11:3; - uint64_t speed_msb:1; - uint64_t reserved_4_7:4; - uint64_t slottime:1; - uint64_t duplex:1; - uint64_t speed:1; - uint64_t en:1; - } cn52xx; -}; - -union cvmx_gmxx_rxx_adr_ctl { - uint64_t u64; - struct cvmx_gmxx_rxx_adr_ctl_s { - uint64_t reserved_4_63:60; - uint64_t cam_mode:1; - uint64_t mcst:2; - uint64_t bcst:1; - } s; -}; - -union cvmx_pip_prt_tagx { - uint64_t u64; - struct cvmx_pip_prt_tagx_s { - uint64_t reserved_54_63:10; - uint64_t portadd_en:1; - uint64_t inc_hwchk:1; - uint64_t reserved_50_51:2; - uint64_t grptagbase_msb:2; - uint64_t reserved_46_47:2; - uint64_t grptagmask_msb:2; - uint64_t reserved_42_43:2; - uint64_t grp_msb:2; - uint64_t grptagbase:4; - uint64_t grptagmask:4; - uint64_t grptag:1; - uint64_t grptag_mskip:1; - uint64_t tag_mode:2; - uint64_t inc_vs:2; - uint64_t inc_vlan:1; - uint64_t inc_prt_flag:1; - uint64_t ip6_dprt_flag:1; - uint64_t ip4_dprt_flag:1; - uint64_t ip6_sprt_flag:1; - uint64_t ip4_sprt_flag:1; - uint64_t ip6_nxth_flag:1; - uint64_t ip4_pctl_flag:1; - uint64_t ip6_dst_flag:1; - uint64_t ip4_dst_flag:1; - uint64_t ip6_src_flag:1; - uint64_t ip4_src_flag:1; - uint64_t tcp6_tag_type:2; - uint64_t tcp4_tag_type:2; - uint64_t ip6_tag_type:2; - uint64_t ip4_tag_type:2; - uint64_t non_tag_type:2; - uint64_t grp:4; - } s; - struct cvmx_pip_prt_tagx_cn30xx { - uint64_t reserved_40_63:24; - uint64_t grptagbase:4; - uint64_t grptagmask:4; - uint64_t grptag:1; - uint64_t reserved_30_30:1; - uint64_t tag_mode:2; - uint64_t inc_vs:2; - uint64_t inc_vlan:1; - uint64_t inc_prt_flag:1; - uint64_t ip6_dprt_flag:1; - uint64_t ip4_dprt_flag:1; - uint64_t ip6_sprt_flag:1; - uint64_t ip4_sprt_flag:1; - uint64_t ip6_nxth_flag:1; - uint64_t ip4_pctl_flag:1; - uint64_t ip6_dst_flag:1; - uint64_t ip4_dst_flag:1; - uint64_t ip6_src_flag:1; - uint64_t ip4_src_flag:1; - uint64_t tcp6_tag_type:2; - uint64_t tcp4_tag_type:2; - uint64_t ip6_tag_type:2; - uint64_t ip4_tag_type:2; - uint64_t non_tag_type:2; - uint64_t grp:4; - } cn30xx; - struct cvmx_pip_prt_tagx_cn50xx { - uint64_t reserved_40_63:24; - uint64_t grptagbase:4; - uint64_t grptagmask:4; - uint64_t grptag:1; - uint64_t grptag_mskip:1; - uint64_t tag_mode:2; - uint64_t inc_vs:2; - uint64_t inc_vlan:1; - uint64_t inc_prt_flag:1; - uint64_t ip6_dprt_flag:1; - uint64_t ip4_dprt_flag:1; - uint64_t ip6_sprt_flag:1; - uint64_t ip4_sprt_flag:1; - uint64_t ip6_nxth_flag:1; - uint64_t ip4_pctl_flag:1; - uint64_t ip6_dst_flag:1; - uint64_t ip4_dst_flag:1; - uint64_t ip6_src_flag:1; - uint64_t ip4_src_flag:1; - uint64_t tcp6_tag_type:2; - uint64_t tcp4_tag_type:2; - uint64_t ip6_tag_type:2; - uint64_t ip4_tag_type:2; - uint64_t non_tag_type:2; - uint64_t grp:4; - } cn50xx; -}; - -union cvmx_spxx_int_reg { - uint64_t u64; - struct cvmx_spxx_int_reg_s { - uint64_t reserved_32_63:32; - uint64_t spf:1; - uint64_t reserved_12_30:19; - uint64_t calerr:1; - uint64_t syncerr:1; - uint64_t diperr:1; - uint64_t tpaovr:1; - uint64_t rsverr:1; - uint64_t drwnng:1; - uint64_t clserr:1; - uint64_t spiovr:1; - uint64_t reserved_2_3:2; - uint64_t abnorm:1; - uint64_t prtnxa:1; - } s; -}; - -union cvmx_spxx_int_msk { - uint64_t u64; - struct cvmx_spxx_int_msk_s { - uint64_t reserved_12_63:52; - uint64_t calerr:1; - uint64_t syncerr:1; - uint64_t diperr:1; - uint64_t tpaovr:1; - uint64_t rsverr:1; - uint64_t drwnng:1; - uint64_t clserr:1; - uint64_t spiovr:1; - uint64_t reserved_2_3:2; - uint64_t abnorm:1; - uint64_t prtnxa:1; - } s; -}; - -union cvmx_pow_wq_int { - uint64_t u64; - struct cvmx_pow_wq_int_s { - uint64_t wq_int:16; - uint64_t iq_dis:16; - uint64_t reserved_32_63:32; - } s; -}; - -union cvmx_sso_wq_int_thrx { - uint64_t u64; - struct { - uint64_t iq_thr:12; - uint64_t reserved_12_13:2; - uint64_t ds_thr:12; - uint64_t reserved_26_27:2; - uint64_t tc_thr:4; - uint64_t tc_en:1; - uint64_t reserved_33_63:31; - } s; -}; - -union cvmx_stxx_int_reg { - uint64_t u64; - struct cvmx_stxx_int_reg_s { - uint64_t reserved_9_63:55; - uint64_t syncerr:1; - uint64_t frmerr:1; - uint64_t unxfrm:1; - uint64_t nosync:1; - uint64_t diperr:1; - uint64_t datovr:1; - uint64_t ovrbst:1; - uint64_t calpar1:1; - uint64_t calpar0:1; - } s; -}; - -union cvmx_stxx_int_msk { - uint64_t u64; - struct cvmx_stxx_int_msk_s { - uint64_t reserved_8_63:56; - uint64_t frmerr:1; - uint64_t unxfrm:1; - uint64_t nosync:1; - uint64_t diperr:1; - uint64_t datovr:1; - uint64_t ovrbst:1; - uint64_t calpar1:1; - uint64_t calpar0:1; - } s; -}; - -union cvmx_pow_wq_int_pc { - uint64_t u64; - struct cvmx_pow_wq_int_pc_s { - uint64_t reserved_0_7:8; - uint64_t pc_thr:20; - uint64_t reserved_28_31:4; - uint64_t pc:28; - uint64_t reserved_60_63:4; - } s; -}; - -union cvmx_pow_wq_int_thrx { - uint64_t u64; - struct cvmx_pow_wq_int_thrx_s { - uint64_t reserved_29_63:35; - uint64_t tc_en:1; - uint64_t tc_thr:4; - uint64_t reserved_23_23:1; - uint64_t ds_thr:11; - uint64_t reserved_11_11:1; - uint64_t iq_thr:11; - } s; - struct cvmx_pow_wq_int_thrx_cn30xx { - uint64_t reserved_29_63:35; - uint64_t tc_en:1; - uint64_t tc_thr:4; - uint64_t reserved_18_23:6; - uint64_t ds_thr:6; - uint64_t reserved_6_11:6; - uint64_t iq_thr:6; - } cn30xx; - struct cvmx_pow_wq_int_thrx_cn31xx { - uint64_t reserved_29_63:35; - uint64_t tc_en:1; - uint64_t tc_thr:4; - uint64_t reserved_20_23:4; - uint64_t ds_thr:8; - uint64_t reserved_8_11:4; - uint64_t iq_thr:8; - } cn31xx; - struct cvmx_pow_wq_int_thrx_cn52xx { - uint64_t reserved_29_63:35; - uint64_t tc_en:1; - uint64_t tc_thr:4; - uint64_t reserved_21_23:3; - uint64_t ds_thr:9; - uint64_t reserved_9_11:3; - uint64_t iq_thr:9; - } cn52xx; - struct cvmx_pow_wq_int_thrx_cn63xx { - uint64_t reserved_29_63:35; - uint64_t tc_en:1; - uint64_t tc_thr:4; - uint64_t reserved_22_23:2; - uint64_t ds_thr:10; - uint64_t reserved_10_11:2; - uint64_t iq_thr:10; - } cn63xx; -}; - -union cvmx_npi_rsl_int_blocks { - uint64_t u64; - struct cvmx_npi_rsl_int_blocks_s { - uint64_t reserved_32_63:32; - uint64_t rint_31:1; - uint64_t iob:1; - uint64_t reserved_28_29:2; - uint64_t rint_27:1; - uint64_t rint_26:1; - uint64_t rint_25:1; - uint64_t rint_24:1; - uint64_t asx1:1; - uint64_t asx0:1; - uint64_t rint_21:1; - uint64_t pip:1; - uint64_t spx1:1; - uint64_t spx0:1; - uint64_t lmc:1; - uint64_t l2c:1; - uint64_t rint_15:1; - uint64_t reserved_13_14:2; - uint64_t pow:1; - uint64_t tim:1; - uint64_t pko:1; - uint64_t ipd:1; - uint64_t rint_8:1; - uint64_t zip:1; - uint64_t dfa:1; - uint64_t fpa:1; - uint64_t key:1; - uint64_t npi:1; - uint64_t gmx1:1; - uint64_t gmx0:1; - uint64_t mio:1; - } s; - struct cvmx_npi_rsl_int_blocks_cn30xx { - uint64_t reserved_32_63:32; - uint64_t rint_31:1; - uint64_t iob:1; - uint64_t rint_29:1; - uint64_t rint_28:1; - uint64_t rint_27:1; - uint64_t rint_26:1; - uint64_t rint_25:1; - uint64_t rint_24:1; - uint64_t asx1:1; - uint64_t asx0:1; - uint64_t rint_21:1; - uint64_t pip:1; - uint64_t spx1:1; - uint64_t spx0:1; - uint64_t lmc:1; - uint64_t l2c:1; - uint64_t rint_15:1; - uint64_t rint_14:1; - uint64_t usb:1; - uint64_t pow:1; - uint64_t tim:1; - uint64_t pko:1; - uint64_t ipd:1; - uint64_t rint_8:1; - uint64_t zip:1; - uint64_t dfa:1; - uint64_t fpa:1; - uint64_t key:1; - uint64_t npi:1; - uint64_t gmx1:1; - uint64_t gmx0:1; - uint64_t mio:1; - } cn30xx; - struct cvmx_npi_rsl_int_blocks_cn38xx { - uint64_t reserved_32_63:32; - uint64_t rint_31:1; - uint64_t iob:1; - uint64_t rint_29:1; - uint64_t rint_28:1; - uint64_t rint_27:1; - uint64_t rint_26:1; - uint64_t rint_25:1; - uint64_t rint_24:1; - uint64_t asx1:1; - uint64_t asx0:1; - uint64_t rint_21:1; - uint64_t pip:1; - uint64_t spx1:1; - uint64_t spx0:1; - uint64_t lmc:1; - uint64_t l2c:1; - uint64_t rint_15:1; - uint64_t rint_14:1; - uint64_t rint_13:1; - uint64_t pow:1; - uint64_t tim:1; - uint64_t pko:1; - uint64_t ipd:1; - uint64_t rint_8:1; - uint64_t zip:1; - uint64_t dfa:1; - uint64_t fpa:1; - uint64_t key:1; - uint64_t npi:1; - uint64_t gmx1:1; - uint64_t gmx0:1; - uint64_t mio:1; - } cn38xx; - struct cvmx_npi_rsl_int_blocks_cn50xx { - uint64_t reserved_31_63:33; - uint64_t iob:1; - uint64_t lmc1:1; - uint64_t agl:1; - uint64_t reserved_24_27:4; - uint64_t asx1:1; - uint64_t asx0:1; - uint64_t reserved_21_21:1; - uint64_t pip:1; - uint64_t spx1:1; - uint64_t spx0:1; - uint64_t lmc:1; - uint64_t l2c:1; - uint64_t reserved_15_15:1; - uint64_t rad:1; - uint64_t usb:1; - uint64_t pow:1; - uint64_t tim:1; - uint64_t pko:1; - uint64_t ipd:1; - uint64_t reserved_8_8:1; - uint64_t zip:1; - uint64_t dfa:1; - uint64_t fpa:1; - uint64_t key:1; - uint64_t npi:1; - uint64_t gmx1:1; - uint64_t gmx0:1; - uint64_t mio:1; - } cn50xx; -}; - -union cvmx_pko_command_word0 { - uint64_t u64; - struct { - uint64_t total_bytes:16; - uint64_t segs:6; - uint64_t dontfree:1; - uint64_t ignore_i:1; - uint64_t ipoffp1:7; - uint64_t gather:1; - uint64_t rsp:1; - uint64_t wqp:1; - uint64_t n2:1; - uint64_t le:1; - uint64_t reg0:11; - uint64_t subone0:1; - uint64_t reg1:11; - uint64_t subone1:1; - uint64_t size0:2; - uint64_t size1:2; - } s; -}; - -union cvmx_ciu_timx { - uint64_t u64; - struct cvmx_ciu_timx_s { - uint64_t reserved_37_63:27; - uint64_t one_shot:1; - uint64_t len:36; - } s; -}; - -union cvmx_gmxx_rxx_rx_inbnd { - uint64_t u64; - struct cvmx_gmxx_rxx_rx_inbnd_s { - uint64_t status:1; - uint64_t speed:2; - uint64_t duplex:1; - uint64_t reserved_4_63:60; - } s; -}; - -static inline int32_t cvmx_fau_fetch_and_add32(enum cvmx_fau_reg_32 reg, - int32_t value) -{ - return value; -} - -static inline void cvmx_fau_atomic_add32(enum cvmx_fau_reg_32 reg, - int32_t value) -{ } - -static inline void cvmx_fau_atomic_write32(enum cvmx_fau_reg_32 reg, - int32_t value) -{ } - -static inline uint64_t cvmx_scratch_read64(uint64_t address) -{ - return 0; -} - -static inline void cvmx_scratch_write64(uint64_t address, uint64_t value) -{ } - -static inline int cvmx_wqe_get_grp(struct cvmx_wqe *work) -{ - return 0; -} - -static inline void *cvmx_phys_to_ptr(uint64_t physical_address) -{ - return (void *)(uintptr_t)(physical_address); -} - -static inline uint64_t cvmx_ptr_to_phys(void *ptr) -{ - return (unsigned long)ptr; -} - -static inline int cvmx_helper_get_interface_num(int ipd_port) -{ - return ipd_port; -} - -static inline int cvmx_helper_get_interface_index_num(int ipd_port) -{ - return ipd_port; -} - -static inline void cvmx_fpa_enable(void) -{ } - -static inline uint64_t cvmx_read_csr(uint64_t csr_addr) -{ - return 0; -} - -static inline void cvmx_write_csr(uint64_t csr_addr, uint64_t val) -{ } - -static inline int cvmx_helper_setup_red(int pass_thresh, int drop_thresh) -{ - return 0; -} - -static inline void *cvmx_fpa_alloc(uint64_t pool) -{ - return NULL; -} - -static inline void cvmx_fpa_free(void *ptr, uint64_t pool, - uint64_t num_cache_lines) -{ } - -static inline int octeon_is_simulation(void) -{ - return 1; -} - -static inline void cvmx_pip_get_port_status(uint64_t port_num, uint64_t clear, - cvmx_pip_port_status_t *status) -{ } - -static inline void cvmx_pko_get_port_status(uint64_t port_num, uint64_t clear, - cvmx_pko_port_status_t *status) -{ } - -static inline cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int - interface) -{ - return 0; -} - -static inline union cvmx_helper_link_info cvmx_helper_link_get(int ipd_port) -{ - union cvmx_helper_link_info ret = { .u64 = 0 }; - - return ret; -} - -static inline int cvmx_helper_link_set(int ipd_port, - union cvmx_helper_link_info link_info) -{ - return 0; -} - -static inline int cvmx_helper_initialize_packet_io_global(void) -{ - return 0; -} - -static inline int cvmx_helper_get_number_of_interfaces(void) -{ - return 2; -} - -static inline int cvmx_helper_ports_on_interface(int interface) -{ - return 1; -} - -static inline int cvmx_helper_get_ipd_port(int interface, int port) -{ - return 0; -} - -static inline int cvmx_helper_ipd_and_packet_input_enable(void) -{ - return 0; -} - -static inline void cvmx_ipd_disable(void) -{ } - -static inline void cvmx_ipd_free_ptr(void) -{ } - -static inline void cvmx_pko_disable(void) -{ } - -static inline void cvmx_pko_shutdown(void) -{ } - -static inline int cvmx_pko_get_base_queue_per_core(int port, int core) -{ - return port; -} - -static inline int cvmx_pko_get_base_queue(int port) -{ - return port; -} - -static inline int cvmx_pko_get_num_queues(int port) -{ - return port; -} - -static inline unsigned int cvmx_get_core_num(void) -{ - return 0; -} - -static inline void cvmx_pow_work_request_async_nocheck(int scr_addr, - cvmx_pow_wait_t wait) -{ } - -static inline void cvmx_pow_work_request_async(int scr_addr, - cvmx_pow_wait_t wait) -{ } - -static inline struct cvmx_wqe *cvmx_pow_work_response_async(int scr_addr) -{ - struct cvmx_wqe *wqe = (void *)(unsigned long)scr_addr; - - return wqe; -} - -static inline struct cvmx_wqe *cvmx_pow_work_request_sync(cvmx_pow_wait_t wait) -{ - return (void *)(unsigned long)wait; -} - -static inline int cvmx_spi_restart_interface(int interface, - cvmx_spi_mode_t mode, int timeout) -{ - return 0; -} - -static inline void cvmx_fau_async_fetch_and_add32(uint64_t scraddr, - enum cvmx_fau_reg_32 reg, - int32_t value) -{ } - -static inline union cvmx_gmxx_rxx_rx_inbnd cvmx_spi4000_check_speed( - int interface, - int port) -{ - union cvmx_gmxx_rxx_rx_inbnd r; - - r.u64 = 0; - return r; -} - -static inline void cvmx_pko_send_packet_prepare(uint64_t port, uint64_t queue, - cvmx_pko_lock_t use_locking) -{ } - -static inline cvmx_pko_status_t cvmx_pko_send_packet_finish(uint64_t port, - uint64_t queue, union cvmx_pko_command_word0 pko_command, - union cvmx_buf_ptr packet, cvmx_pko_lock_t use_locking) -{ - return 0; -} - -static inline void cvmx_wqe_set_port(struct cvmx_wqe *work, int port) -{ } - -static inline void cvmx_wqe_set_qos(struct cvmx_wqe *work, int qos) -{ } - -static inline int cvmx_wqe_get_qos(struct cvmx_wqe *work) -{ - return 0; -} - -static inline void cvmx_wqe_set_grp(struct cvmx_wqe *work, int grp) -{ } - -static inline void cvmx_pow_work_submit(struct cvmx_wqe *wqp, uint32_t tag, - enum cvmx_pow_tag_type tag_type, - uint64_t qos, uint64_t grp) -{ } - -#define CVMX_ASXX_RX_CLK_SETX(a, b) ((a)+(b)) -#define CVMX_ASXX_TX_CLK_SETX(a, b) ((a)+(b)) -#define CVMX_CIU_TIMX(a) (a) -#define CVMX_GMXX_RXX_ADR_CAM0(a, b) ((a)+(b)) -#define CVMX_GMXX_RXX_ADR_CAM1(a, b) ((a)+(b)) -#define CVMX_GMXX_RXX_ADR_CAM2(a, b) ((a)+(b)) -#define CVMX_GMXX_RXX_ADR_CAM3(a, b) ((a)+(b)) -#define CVMX_GMXX_RXX_ADR_CAM4(a, b) ((a)+(b)) -#define CVMX_GMXX_RXX_ADR_CAM5(a, b) ((a)+(b)) -#define CVMX_GMXX_RXX_FRM_CTL(a, b) ((a)+(b)) -#define CVMX_GMXX_RXX_INT_REG(a, b) ((a)+(b)) -#define CVMX_GMXX_SMACX(a, b) ((a)+(b)) -#define CVMX_PIP_PRT_TAGX(a) (a) -#define CVMX_POW_PP_GRP_MSKX(a) (a) -#define CVMX_POW_WQ_INT_THRX(a) (a) -#define CVMX_SPXX_INT_MSK(a) (a) -#define CVMX_SPXX_INT_REG(a) (a) -#define CVMX_SSO_PPX_GRP_MSK(a) (a) -#define CVMX_SSO_WQ_INT_THRX(a) (a) -#define CVMX_STXX_INT_MSK(a) (a) -#define CVMX_STXX_INT_REG(a) (a) From 95ace52e4036482da1895b6e19f15141802cc3dd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 10 Dec 2019 10:15:09 +0100 Subject: [PATCH 090/353] staging: octeon-usb: delete the octeon usb host controller driver This driver was merged back in 2013 and shows no progress toward every being merged into the "correct" part of the kernel. The code doesn't even build for anyone unless you have the specific hardware platform selected, so odds are it doesn't even work anymore. Remove it for now and is someone comes along that has the hardware and is willing to fix it up, it can be reverted. Cc: Aaro Koskinen Cc: David Daney Cc: Nishka Dasgupta Cc: Himadri Pandya Cc: "Frank A. Cancio Bello" Cc: Sumit Pundir Cc: Laura Lazzati Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20191210091509.3546251-2-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/octeon-usb/Kconfig | 11 - drivers/staging/octeon-usb/Makefile | 2 - drivers/staging/octeon-usb/TODO | 8 - drivers/staging/octeon-usb/octeon-hcd.c | 3737 ----------------------- drivers/staging/octeon-usb/octeon-hcd.h | 1847 ----------- 7 files changed, 5608 deletions(-) delete mode 100644 drivers/staging/octeon-usb/Kconfig delete mode 100644 drivers/staging/octeon-usb/Makefile delete mode 100644 drivers/staging/octeon-usb/TODO delete mode 100644 drivers/staging/octeon-usb/octeon-hcd.c delete mode 100644 drivers/staging/octeon-usb/octeon-hcd.h diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index f1926e8abc80..baccd7c883cc 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -42,8 +42,6 @@ source "drivers/staging/rtl8188eu/Kconfig" source "drivers/staging/rts5208/Kconfig" -source "drivers/staging/octeon-usb/Kconfig" - source "drivers/staging/vt6655/Kconfig" source "drivers/staging/vt6656/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index d5411677a45f..463aef6a18ef 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -12,7 +12,6 @@ obj-$(CONFIG_R8712U) += rtl8712/ obj-$(CONFIG_R8188EU) += rtl8188eu/ obj-$(CONFIG_RTS5208) += rts5208/ obj-$(CONFIG_NETLOGIC_XLR_NET) += netlogic/ -obj-$(CONFIG_OCTEON_USB) += octeon-usb/ obj-$(CONFIG_VT6655) += vt6655/ obj-$(CONFIG_VT6656) += vt6656/ obj-$(CONFIG_VME_BUS) += vme/ diff --git a/drivers/staging/octeon-usb/Kconfig b/drivers/staging/octeon-usb/Kconfig deleted file mode 100644 index 6a5d842ee0f2..000000000000 --- a/drivers/staging/octeon-usb/Kconfig +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config OCTEON_USB - tristate "Cavium Networks Octeon USB support" - depends on CAVIUM_OCTEON_SOC && USB - help - This driver supports USB host controller on some Cavium - Networks' products in the Octeon family. - - To compile this driver as a module, choose M here. The module - will be called octeon-hcd. - diff --git a/drivers/staging/octeon-usb/Makefile b/drivers/staging/octeon-usb/Makefile deleted file mode 100644 index 9873a0130ad5..000000000000 --- a/drivers/staging/octeon-usb/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-${CONFIG_OCTEON_USB} := octeon-hcd.o diff --git a/drivers/staging/octeon-usb/TODO b/drivers/staging/octeon-usb/TODO deleted file mode 100644 index 2b29acca5caa..000000000000 --- a/drivers/staging/octeon-usb/TODO +++ /dev/null @@ -1,8 +0,0 @@ -This driver is functional and has been tested on EdgeRouter Lite, -D-Link DSR-1000N and EBH5600 evaluation board with USB mass storage. - -TODO: - - kernel coding style - - checkpatch warnings - -Contact: Aaro Koskinen diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c deleted file mode 100644 index 582c9187559d..000000000000 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ /dev/null @@ -1,3737 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2008 Cavium Networks - * - * Some parts of the code were originally released under BSD license: - * - * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * * Neither the name of Cavium Networks nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * This Software, including technical data, may be subject to U.S. export - * control laws, including the U.S. Export Administration Act and its associated - * regulations, and may be subject to export or import regulations in other - * countries. - * - * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" - * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR - * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO - * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION - * OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM - * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, - * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF - * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR - * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR - * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "octeon-hcd.h" - -/** - * enum cvmx_usb_speed - the possible USB device speeds - * - * @CVMX_USB_SPEED_HIGH: Device is operation at 480Mbps - * @CVMX_USB_SPEED_FULL: Device is operation at 12Mbps - * @CVMX_USB_SPEED_LOW: Device is operation at 1.5Mbps - */ -enum cvmx_usb_speed { - CVMX_USB_SPEED_HIGH = 0, - CVMX_USB_SPEED_FULL = 1, - CVMX_USB_SPEED_LOW = 2, -}; - -/** - * enum cvmx_usb_transfer - the possible USB transfer types - * - * @CVMX_USB_TRANSFER_CONTROL: USB transfer type control for hub and status - * transfers - * @CVMX_USB_TRANSFER_ISOCHRONOUS: USB transfer type isochronous for low - * priority periodic transfers - * @CVMX_USB_TRANSFER_BULK: USB transfer type bulk for large low priority - * transfers - * @CVMX_USB_TRANSFER_INTERRUPT: USB transfer type interrupt for high priority - * periodic transfers - */ -enum cvmx_usb_transfer { - CVMX_USB_TRANSFER_CONTROL = 0, - CVMX_USB_TRANSFER_ISOCHRONOUS = 1, - CVMX_USB_TRANSFER_BULK = 2, - CVMX_USB_TRANSFER_INTERRUPT = 3, -}; - -/** - * enum cvmx_usb_direction - the transfer directions - * - * @CVMX_USB_DIRECTION_OUT: Data is transferring from Octeon to the device/host - * @CVMX_USB_DIRECTION_IN: Data is transferring from the device/host to Octeon - */ -enum cvmx_usb_direction { - CVMX_USB_DIRECTION_OUT, - CVMX_USB_DIRECTION_IN, -}; - -/** - * enum cvmx_usb_status - possible callback function status codes - * - * @CVMX_USB_STATUS_OK: The transaction / operation finished without - * any errors - * @CVMX_USB_STATUS_SHORT: FIXME: This is currently not implemented - * @CVMX_USB_STATUS_CANCEL: The transaction was canceled while in flight - * by a user call to cvmx_usb_cancel - * @CVMX_USB_STATUS_ERROR: The transaction aborted with an unexpected - * error status - * @CVMX_USB_STATUS_STALL: The transaction received a USB STALL response - * from the device - * @CVMX_USB_STATUS_XACTERR: The transaction failed with an error from the - * device even after a number of retries - * @CVMX_USB_STATUS_DATATGLERR: The transaction failed with a data toggle - * error even after a number of retries - * @CVMX_USB_STATUS_BABBLEERR: The transaction failed with a babble error - * @CVMX_USB_STATUS_FRAMEERR: The transaction failed with a frame error - * even after a number of retries - */ -enum cvmx_usb_status { - CVMX_USB_STATUS_OK, - CVMX_USB_STATUS_SHORT, - CVMX_USB_STATUS_CANCEL, - CVMX_USB_STATUS_ERROR, - CVMX_USB_STATUS_STALL, - CVMX_USB_STATUS_XACTERR, - CVMX_USB_STATUS_DATATGLERR, - CVMX_USB_STATUS_BABBLEERR, - CVMX_USB_STATUS_FRAMEERR, -}; - -/** - * struct cvmx_usb_port_status - the USB port status information - * - * @port_enabled: 1 = Usb port is enabled, 0 = disabled - * @port_over_current: 1 = Over current detected, 0 = Over current not - * detected. Octeon doesn't support over current detection. - * @port_powered: 1 = Port power is being supplied to the device, 0 = - * power is off. Octeon doesn't support turning port power - * off. - * @port_speed: Current port speed. - * @connected: 1 = A device is connected to the port, 0 = No device is - * connected. - * @connect_change: 1 = Device connected state changed since the last set - * status call. - */ -struct cvmx_usb_port_status { - u32 reserved : 25; - u32 port_enabled : 1; - u32 port_over_current : 1; - u32 port_powered : 1; - enum cvmx_usb_speed port_speed : 2; - u32 connected : 1; - u32 connect_change : 1; -}; - -/** - * struct cvmx_usb_iso_packet - descriptor for Isochronous packets - * - * @offset: This is the offset in bytes into the main buffer where this data - * is stored. - * @length: This is the length in bytes of the data. - * @status: This is the status of this individual packet transfer. - */ -struct cvmx_usb_iso_packet { - int offset; - int length; - enum cvmx_usb_status status; -}; - -/** - * enum cvmx_usb_initialize_flags - flags used by the initialization function - * - * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI: The USB port uses a 12MHz crystal - * as clock source at USB_XO and - * USB_XI. - * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND: The USB port uses 12/24/48MHz 2.5V - * board clock source at USB_XO. - * USB_XI should be tied to GND. - * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK: Mask for clock speed field - * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ: Speed of reference clock or - * crystal - * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ: Speed of reference clock - * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ: Speed of reference clock - * @CVMX_USB_INITIALIZE_FLAGS_NO_DMA: Disable DMA and used polled IO for - * data transfer use for the USB - */ -enum cvmx_usb_initialize_flags { - CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI = 1 << 0, - CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND = 1 << 1, - CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK = 3 << 3, - CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ = 1 << 3, - CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ = 2 << 3, - CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ = 3 << 3, - /* Bits 3-4 used to encode the clock frequency */ - CVMX_USB_INITIALIZE_FLAGS_NO_DMA = 1 << 5, -}; - -/** - * enum cvmx_usb_pipe_flags - internal flags for a pipe. - * - * @CVMX_USB_PIPE_FLAGS_SCHEDULED: Used internally to determine if a pipe is - * actively using hardware. - * @CVMX_USB_PIPE_FLAGS_NEED_PING: Used internally to determine if a high speed - * pipe is in the ping state. - */ -enum cvmx_usb_pipe_flags { - CVMX_USB_PIPE_FLAGS_SCHEDULED = 1 << 17, - CVMX_USB_PIPE_FLAGS_NEED_PING = 1 << 18, -}; - -/* Maximum number of times to retry failed transactions */ -#define MAX_RETRIES 3 - -/* Maximum number of hardware channels supported by the USB block */ -#define MAX_CHANNELS 8 - -/* - * The low level hardware can transfer a maximum of this number of bytes in each - * transfer. The field is 19 bits wide - */ -#define MAX_TRANSFER_BYTES ((1 << 19) - 1) - -/* - * The low level hardware can transfer a maximum of this number of packets in - * each transfer. The field is 10 bits wide - */ -#define MAX_TRANSFER_PACKETS ((1 << 10) - 1) - -/** - * Logical transactions may take numerous low level - * transactions, especially when splits are concerned. This - * enum represents all of the possible stages a transaction can - * be in. Note that split completes are always even. This is so - * the NAK handler can backup to the previous low level - * transaction with a simple clearing of bit 0. - */ -enum cvmx_usb_stage { - CVMX_USB_STAGE_NON_CONTROL, - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE, - CVMX_USB_STAGE_SETUP, - CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE, - CVMX_USB_STAGE_DATA, - CVMX_USB_STAGE_DATA_SPLIT_COMPLETE, - CVMX_USB_STAGE_STATUS, - CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE, -}; - -/** - * struct cvmx_usb_transaction - describes each pending USB transaction - * regardless of type. These are linked together - * to form a list of pending requests for a pipe. - * - * @node: List node for transactions in the pipe. - * @type: Type of transaction, duplicated of the pipe. - * @flags: State flags for this transaction. - * @buffer: User's physical buffer address to read/write. - * @buffer_length: Size of the user's buffer in bytes. - * @control_header: For control transactions, physical address of the 8 - * byte standard header. - * @iso_start_frame: For ISO transactions, the starting frame number. - * @iso_number_packets: For ISO transactions, the number of packets in the - * request. - * @iso_packets: For ISO transactions, the sub packets in the request. - * @actual_bytes: Actual bytes transfer for this transaction. - * @stage: For control transactions, the current stage. - * @urb: URB. - */ -struct cvmx_usb_transaction { - struct list_head node; - enum cvmx_usb_transfer type; - u64 buffer; - int buffer_length; - u64 control_header; - int iso_start_frame; - int iso_number_packets; - struct cvmx_usb_iso_packet *iso_packets; - int xfersize; - int pktcnt; - int retries; - int actual_bytes; - enum cvmx_usb_stage stage; - struct urb *urb; -}; - -/** - * struct cvmx_usb_pipe - a pipe represents a virtual connection between Octeon - * and some USB device. It contains a list of pending - * request to the device. - * - * @node: List node for pipe list - * @next: Pipe after this one in the list - * @transactions: List of pending transactions - * @interval: For periodic pipes, the interval between packets in - * frames - * @next_tx_frame: The next frame this pipe is allowed to transmit on - * @flags: State flags for this pipe - * @device_speed: Speed of device connected to this pipe - * @transfer_type: Type of transaction supported by this pipe - * @transfer_dir: IN or OUT. Ignored for Control - * @multi_count: Max packet in a row for the device - * @max_packet: The device's maximum packet size in bytes - * @device_addr: USB device address at other end of pipe - * @endpoint_num: USB endpoint number at other end of pipe - * @hub_device_addr: Hub address this device is connected to - * @hub_port: Hub port this device is connected to - * @pid_toggle: This toggles between 0/1 on every packet send to track - * the data pid needed - * @channel: Hardware DMA channel for this pipe - * @split_sc_frame: The low order bits of the frame number the split - * complete should be sent on - */ -struct cvmx_usb_pipe { - struct list_head node; - struct list_head transactions; - u64 interval; - u64 next_tx_frame; - enum cvmx_usb_pipe_flags flags; - enum cvmx_usb_speed device_speed; - enum cvmx_usb_transfer transfer_type; - enum cvmx_usb_direction transfer_dir; - int multi_count; - u16 max_packet; - u8 device_addr; - u8 endpoint_num; - u8 hub_device_addr; - u8 hub_port; - u8 pid_toggle; - u8 channel; - s8 split_sc_frame; -}; - -struct cvmx_usb_tx_fifo { - struct { - int channel; - int size; - u64 address; - } entry[MAX_CHANNELS + 1]; - int head; - int tail; -}; - -/** - * struct octeon_hcd - the state of the USB block - * - * lock: Serialization lock. - * init_flags: Flags passed to initialize. - * index: Which USB block this is for. - * idle_hardware_channels: Bit set for every idle hardware channel. - * usbcx_hprt: Stored port status so we don't need to read a CSR to - * determine splits. - * pipe_for_channel: Map channels to pipes. - * pipe: Storage for pipes. - * indent: Used by debug output to indent functions. - * port_status: Last port status used for change notification. - * idle_pipes: List of open pipes that have no transactions. - * active_pipes: Active pipes indexed by transfer type. - * frame_number: Increments every SOF interrupt for time keeping. - * active_split: Points to the current active split, or NULL. - */ -struct octeon_hcd { - spinlock_t lock; /* serialization lock */ - int init_flags; - int index; - int idle_hardware_channels; - union cvmx_usbcx_hprt usbcx_hprt; - struct cvmx_usb_pipe *pipe_for_channel[MAX_CHANNELS]; - int indent; - struct cvmx_usb_port_status port_status; - struct list_head idle_pipes; - struct list_head active_pipes[4]; - u64 frame_number; - struct cvmx_usb_transaction *active_split; - struct cvmx_usb_tx_fifo periodic; - struct cvmx_usb_tx_fifo nonperiodic; -}; - -/* - * This macro logically sets a single field in a CSR. It does the sequence - * read, modify, and write - */ -#define USB_SET_FIELD32(address, _union, field, value) \ - do { \ - union _union c; \ - \ - c.u32 = cvmx_usb_read_csr32(usb, address); \ - c.s.field = value; \ - cvmx_usb_write_csr32(usb, address, c.u32); \ - } while (0) - -/* Returns the IO address to push/pop stuff data from the FIFOs */ -#define USB_FIFO_ADDRESS(channel, usb_index) \ - (CVMX_USBCX_GOTGCTL(usb_index) + ((channel) + 1) * 0x1000) - -/** - * struct octeon_temp_buffer - a bounce buffer for USB transfers - * @orig_buffer: the original buffer passed by the USB stack - * @data: the newly allocated temporary buffer (excluding meta-data) - * - * Both the DMA engine and FIFO mode will always transfer full 32-bit words. If - * the buffer is too short, we need to allocate a temporary one, and this struct - * represents it. - */ -struct octeon_temp_buffer { - void *orig_buffer; - u8 data[0]; -}; - -static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p) -{ - return container_of((void *)p, struct usb_hcd, hcd_priv); -} - -/** - * octeon_alloc_temp_buffer - allocate a temporary buffer for USB transfer - * (if needed) - * @urb: URB. - * @mem_flags: Memory allocation flags. - * - * This function allocates a temporary bounce buffer whenever it's needed - * due to HW limitations. - */ -static int octeon_alloc_temp_buffer(struct urb *urb, gfp_t mem_flags) -{ - struct octeon_temp_buffer *temp; - - if (urb->num_sgs || urb->sg || - (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) || - !(urb->transfer_buffer_length % sizeof(u32))) - return 0; - - temp = kmalloc(ALIGN(urb->transfer_buffer_length, sizeof(u32)) + - sizeof(*temp), mem_flags); - if (!temp) - return -ENOMEM; - - temp->orig_buffer = urb->transfer_buffer; - if (usb_urb_dir_out(urb)) - memcpy(temp->data, urb->transfer_buffer, - urb->transfer_buffer_length); - urb->transfer_buffer = temp->data; - urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER; - - return 0; -} - -/** - * octeon_free_temp_buffer - free a temporary buffer used by USB transfers. - * @urb: URB. - * - * Frees a buffer allocated by octeon_alloc_temp_buffer(). - */ -static void octeon_free_temp_buffer(struct urb *urb) -{ - struct octeon_temp_buffer *temp; - size_t length; - - if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) - return; - - temp = container_of(urb->transfer_buffer, struct octeon_temp_buffer, - data); - if (usb_urb_dir_in(urb)) { - if (usb_pipeisoc(urb->pipe)) - length = urb->transfer_buffer_length; - else - length = urb->actual_length; - - memcpy(temp->orig_buffer, urb->transfer_buffer, length); - } - urb->transfer_buffer = temp->orig_buffer; - urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; - kfree(temp); -} - -/** - * octeon_map_urb_for_dma - Octeon-specific map_urb_for_dma(). - * @hcd: USB HCD structure. - * @urb: URB. - * @mem_flags: Memory allocation flags. - */ -static int octeon_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, - gfp_t mem_flags) -{ - int ret; - - ret = octeon_alloc_temp_buffer(urb, mem_flags); - if (ret) - return ret; - - ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); - if (ret) - octeon_free_temp_buffer(urb); - - return ret; -} - -/** - * octeon_unmap_urb_for_dma - Octeon-specific unmap_urb_for_dma() - * @hcd: USB HCD structure. - * @urb: URB. - */ -static void octeon_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) -{ - usb_hcd_unmap_urb_for_dma(hcd, urb); - octeon_free_temp_buffer(urb); -} - -/** - * Read a USB 32bit CSR. It performs the necessary address swizzle - * for 32bit CSRs and logs the value in a readable format if - * debugging is on. - * - * @usb: USB block this access is for - * @address: 64bit address to read - * - * Returns: Result of the read - */ -static inline u32 cvmx_usb_read_csr32(struct octeon_hcd *usb, u64 address) -{ - return cvmx_read64_uint32(address ^ 4); -} - -/** - * Write a USB 32bit CSR. It performs the necessary address - * swizzle for 32bit CSRs and logs the value in a readable format - * if debugging is on. - * - * @usb: USB block this access is for - * @address: 64bit address to write - * @value: Value to write - */ -static inline void cvmx_usb_write_csr32(struct octeon_hcd *usb, - u64 address, u32 value) -{ - cvmx_write64_uint32(address ^ 4, value); - cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index)); -} - -/** - * Return non zero if this pipe connects to a non HIGH speed - * device through a high speed hub. - * - * @usb: USB block this access is for - * @pipe: Pipe to check - * - * Returns: Non zero if we need to do split transactions - */ -static inline int cvmx_usb_pipe_needs_split(struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe) -{ - return pipe->device_speed != CVMX_USB_SPEED_HIGH && - usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_HIGH; -} - -/** - * Trivial utility function to return the correct PID for a pipe - * - * @pipe: pipe to check - * - * Returns: PID for pipe - */ -static inline int cvmx_usb_get_data_pid(struct cvmx_usb_pipe *pipe) -{ - if (pipe->pid_toggle) - return 2; /* Data1 */ - return 0; /* Data0 */ -} - -/* Loops through register until txfflsh or rxfflsh become zero.*/ -static int cvmx_wait_tx_rx(struct octeon_hcd *usb, int fflsh_type) -{ - int result; - u64 address = CVMX_USBCX_GRSTCTL(usb->index); - u64 done = cvmx_get_cycle() + 100 * - (u64)octeon_get_clock_rate / 1000000; - union cvmx_usbcx_grstctl c; - - while (1) { - c.u32 = cvmx_usb_read_csr32(usb, address); - if (fflsh_type == 0 && c.s.txfflsh == 0) { - result = 0; - break; - } else if (fflsh_type == 1 && c.s.rxfflsh == 0) { - result = 0; - break; - } else if (cvmx_get_cycle() > done) { - result = -1; - break; - } - - __delay(100); - } - return result; -} - -static void cvmx_fifo_setup(struct octeon_hcd *usb) -{ - union cvmx_usbcx_ghwcfg3 usbcx_ghwcfg3; - union cvmx_usbcx_gnptxfsiz npsiz; - union cvmx_usbcx_hptxfsiz psiz; - - usbcx_ghwcfg3.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_GHWCFG3(usb->index)); - - /* - * Program the USBC_GRXFSIZ register to select the size of the receive - * FIFO (25%). - */ - USB_SET_FIELD32(CVMX_USBCX_GRXFSIZ(usb->index), cvmx_usbcx_grxfsiz, - rxfdep, usbcx_ghwcfg3.s.dfifodepth / 4); - - /* - * Program the USBC_GNPTXFSIZ register to select the size and the start - * address of the non-periodic transmit FIFO for nonperiodic - * transactions (50%). - */ - npsiz.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index)); - npsiz.s.nptxfdep = usbcx_ghwcfg3.s.dfifodepth / 2; - npsiz.s.nptxfstaddr = usbcx_ghwcfg3.s.dfifodepth / 4; - cvmx_usb_write_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index), npsiz.u32); - - /* - * Program the USBC_HPTXFSIZ register to select the size and start - * address of the periodic transmit FIFO for periodic transactions - * (25%). - */ - psiz.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index)); - psiz.s.ptxfsize = usbcx_ghwcfg3.s.dfifodepth / 4; - psiz.s.ptxfstaddr = 3 * usbcx_ghwcfg3.s.dfifodepth / 4; - cvmx_usb_write_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index), psiz.u32); - - /* Flush all FIFOs */ - USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), - cvmx_usbcx_grstctl, txfnum, 0x10); - USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), - cvmx_usbcx_grstctl, txfflsh, 1); - cvmx_wait_tx_rx(usb, 0); - USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), - cvmx_usbcx_grstctl, rxfflsh, 1); - cvmx_wait_tx_rx(usb, 1); -} - -/** - * Shutdown a USB port after a call to cvmx_usb_initialize(). - * The port should be disabled with all pipes closed when this - * function is called. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * - * Returns: 0 or a negative error code. - */ -static int cvmx_usb_shutdown(struct octeon_hcd *usb) -{ - union cvmx_usbnx_clk_ctl usbn_clk_ctl; - - /* Make sure all pipes are closed */ - if (!list_empty(&usb->idle_pipes) || - !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_ISOCHRONOUS]) || - !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT]) || - !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_CONTROL]) || - !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_BULK])) - return -EBUSY; - - /* Disable the clocks and put them in power on reset */ - usbn_clk_ctl.u64 = cvmx_read64_uint64(CVMX_USBNX_CLK_CTL(usb->index)); - usbn_clk_ctl.s.enable = 1; - usbn_clk_ctl.s.por = 1; - usbn_clk_ctl.s.hclk_rst = 1; - usbn_clk_ctl.s.prst = 0; - usbn_clk_ctl.s.hrst = 0; - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); - return 0; -} - -/** - * Initialize a USB port for use. This must be called before any - * other access to the Octeon USB port is made. The port starts - * off in the disabled state. - * - * @dev: Pointer to struct device for logging purposes. - * @usb: Pointer to struct octeon_hcd. - * - * Returns: 0 or a negative error code. - */ -static int cvmx_usb_initialize(struct device *dev, - struct octeon_hcd *usb) -{ - int channel; - int divisor; - int retries = 0; - union cvmx_usbcx_hcfg usbcx_hcfg; - union cvmx_usbnx_clk_ctl usbn_clk_ctl; - union cvmx_usbcx_gintsts usbc_gintsts; - union cvmx_usbcx_gahbcfg usbcx_gahbcfg; - union cvmx_usbcx_gintmsk usbcx_gintmsk; - union cvmx_usbcx_gusbcfg usbcx_gusbcfg; - union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status; - -retry: - /* - * Power On Reset and PHY Initialization - * - * 1. Wait for DCOK to assert (nothing to do) - * - * 2a. Write USBN0/1_CLK_CTL[POR] = 1 and - * USBN0/1_CLK_CTL[HRST,PRST,HCLK_RST] = 0 - */ - usbn_clk_ctl.u64 = cvmx_read64_uint64(CVMX_USBNX_CLK_CTL(usb->index)); - usbn_clk_ctl.s.por = 1; - usbn_clk_ctl.s.hrst = 0; - usbn_clk_ctl.s.prst = 0; - usbn_clk_ctl.s.hclk_rst = 0; - usbn_clk_ctl.s.enable = 0; - /* - * 2b. Select the USB reference clock/crystal parameters by writing - * appropriate values to USBN0/1_CLK_CTL[P_C_SEL, P_RTYPE, P_COM_ON] - */ - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) { - /* - * The USB port uses 12/24/48MHz 2.5V board clock - * source at USB_XO. USB_XI should be tied to GND. - * Most Octeon evaluation boards require this setting - */ - if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || - OCTEON_IS_MODEL(OCTEON_CN56XX) || - OCTEON_IS_MODEL(OCTEON_CN50XX)) - /* From CN56XX,CN50XX,CN31XX,CN30XX manuals */ - usbn_clk_ctl.s.p_rtype = 2; /* p_rclk=1 & p_xenbn=0 */ - else - /* From CN52XX manual */ - usbn_clk_ctl.s.p_rtype = 1; - - switch (usb->init_flags & - CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK) { - case CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ: - usbn_clk_ctl.s.p_c_sel = 0; - break; - case CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ: - usbn_clk_ctl.s.p_c_sel = 1; - break; - case CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ: - usbn_clk_ctl.s.p_c_sel = 2; - break; - } - } else { - /* - * The USB port uses a 12MHz crystal as clock source - * at USB_XO and USB_XI - */ - if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) - /* From CN31XX,CN30XX manual */ - usbn_clk_ctl.s.p_rtype = 3; /* p_rclk=1 & p_xenbn=1 */ - else - /* From CN56XX,CN52XX,CN50XX manuals. */ - usbn_clk_ctl.s.p_rtype = 0; - - usbn_clk_ctl.s.p_c_sel = 0; - } - /* - * 2c. Select the HCLK via writing USBN0/1_CLK_CTL[DIVIDE, DIVIDE2] and - * setting USBN0/1_CLK_CTL[ENABLE] = 1. Divide the core clock down - * such that USB is as close as possible to 125Mhz - */ - divisor = DIV_ROUND_UP(octeon_get_clock_rate(), 125000000); - /* Lower than 4 doesn't seem to work properly */ - if (divisor < 4) - divisor = 4; - usbn_clk_ctl.s.divide = divisor; - usbn_clk_ctl.s.divide2 = 0; - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); - - /* 2d. Write USBN0/1_CLK_CTL[HCLK_RST] = 1 */ - usbn_clk_ctl.s.hclk_rst = 1; - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); - /* 2e. Wait 64 core-clock cycles for HCLK to stabilize */ - __delay(64); - /* - * 3. Program the power-on reset field in the USBN clock-control - * register: - * USBN_CLK_CTL[POR] = 0 - */ - usbn_clk_ctl.s.por = 0; - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); - /* 4. Wait 1 ms for PHY clock to start */ - mdelay(1); - /* - * 5. Program the Reset input from automatic test equipment field in the - * USBP control and status register: - * USBN_USBP_CTL_STATUS[ATE_RESET] = 1 - */ - usbn_usbp_ctl_status.u64 = - cvmx_read64_uint64(CVMX_USBNX_USBP_CTL_STATUS(usb->index)); - usbn_usbp_ctl_status.s.ate_reset = 1; - cvmx_write64_uint64(CVMX_USBNX_USBP_CTL_STATUS(usb->index), - usbn_usbp_ctl_status.u64); - /* 6. Wait 10 cycles */ - __delay(10); - /* - * 7. Clear ATE_RESET field in the USBN clock-control register: - * USBN_USBP_CTL_STATUS[ATE_RESET] = 0 - */ - usbn_usbp_ctl_status.s.ate_reset = 0; - cvmx_write64_uint64(CVMX_USBNX_USBP_CTL_STATUS(usb->index), - usbn_usbp_ctl_status.u64); - /* - * 8. Program the PHY reset field in the USBN clock-control register: - * USBN_CLK_CTL[PRST] = 1 - */ - usbn_clk_ctl.s.prst = 1; - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); - /* - * 9. Program the USBP control and status register to select host or - * device mode. USBN_USBP_CTL_STATUS[HST_MODE] = 0 for host, = 1 for - * device - */ - usbn_usbp_ctl_status.s.hst_mode = 0; - cvmx_write64_uint64(CVMX_USBNX_USBP_CTL_STATUS(usb->index), - usbn_usbp_ctl_status.u64); - /* 10. Wait 1 us */ - udelay(1); - /* - * 11. Program the hreset_n field in the USBN clock-control register: - * USBN_CLK_CTL[HRST] = 1 - */ - usbn_clk_ctl.s.hrst = 1; - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); - /* 12. Proceed to USB core initialization */ - usbn_clk_ctl.s.enable = 1; - cvmx_write64_uint64(CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); - udelay(1); - - /* - * USB Core Initialization - * - * 1. Read USBC_GHWCFG1, USBC_GHWCFG2, USBC_GHWCFG3, USBC_GHWCFG4 to - * determine USB core configuration parameters. - * - * Nothing needed - * - * 2. Program the following fields in the global AHB configuration - * register (USBC_GAHBCFG) - * DMA mode, USBC_GAHBCFG[DMAEn]: 1 = DMA mode, 0 = slave mode - * Burst length, USBC_GAHBCFG[HBSTLEN] = 0 - * Nonperiodic TxFIFO empty level (slave mode only), - * USBC_GAHBCFG[NPTXFEMPLVL] - * Periodic TxFIFO empty level (slave mode only), - * USBC_GAHBCFG[PTXFEMPLVL] - * Global interrupt mask, USBC_GAHBCFG[GLBLINTRMSK] = 1 - */ - usbcx_gahbcfg.u32 = 0; - usbcx_gahbcfg.s.dmaen = !(usb->init_flags & - CVMX_USB_INITIALIZE_FLAGS_NO_DMA); - usbcx_gahbcfg.s.hbstlen = 0; - usbcx_gahbcfg.s.nptxfemplvl = 1; - usbcx_gahbcfg.s.ptxfemplvl = 1; - usbcx_gahbcfg.s.glblintrmsk = 1; - cvmx_usb_write_csr32(usb, CVMX_USBCX_GAHBCFG(usb->index), - usbcx_gahbcfg.u32); - - /* - * 3. Program the following fields in USBC_GUSBCFG register. - * HS/FS timeout calibration, USBC_GUSBCFG[TOUTCAL] = 0 - * ULPI DDR select, USBC_GUSBCFG[DDRSEL] = 0 - * USB turnaround time, USBC_GUSBCFG[USBTRDTIM] = 0x5 - * PHY low-power clock select, USBC_GUSBCFG[PHYLPWRCLKSEL] = 0 - */ - usbcx_gusbcfg.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_GUSBCFG(usb->index)); - usbcx_gusbcfg.s.toutcal = 0; - usbcx_gusbcfg.s.ddrsel = 0; - usbcx_gusbcfg.s.usbtrdtim = 0x5; - usbcx_gusbcfg.s.phylpwrclksel = 0; - cvmx_usb_write_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index), - usbcx_gusbcfg.u32); - - /* - * 4. The software must unmask the following bits in the USBC_GINTMSK - * register. - * OTG interrupt mask, USBC_GINTMSK[OTGINTMSK] = 1 - * Mode mismatch interrupt mask, USBC_GINTMSK[MODEMISMSK] = 1 - */ - usbcx_gintmsk.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_GINTMSK(usb->index)); - usbcx_gintmsk.s.otgintmsk = 1; - usbcx_gintmsk.s.modemismsk = 1; - usbcx_gintmsk.s.hchintmsk = 1; - usbcx_gintmsk.s.sofmsk = 0; - /* We need RX FIFO interrupts if we don't have DMA */ - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) - usbcx_gintmsk.s.rxflvlmsk = 1; - cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTMSK(usb->index), - usbcx_gintmsk.u32); - - /* - * Disable all channel interrupts. We'll enable them per channel later. - */ - for (channel = 0; channel < 8; channel++) - cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCINTMSKX(channel, usb->index), - 0); - - /* - * Host Port Initialization - * - * 1. Program the host-port interrupt-mask field to unmask, - * USBC_GINTMSK[PRTINT] = 1 - */ - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), - cvmx_usbcx_gintmsk, prtintmsk, 1); - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), - cvmx_usbcx_gintmsk, disconnintmsk, 1); - - /* - * 2. Program the USBC_HCFG register to select full-speed host - * or high-speed host. - */ - usbcx_hcfg.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HCFG(usb->index)); - usbcx_hcfg.s.fslssupp = 0; - usbcx_hcfg.s.fslspclksel = 0; - cvmx_usb_write_csr32(usb, CVMX_USBCX_HCFG(usb->index), usbcx_hcfg.u32); - - cvmx_fifo_setup(usb); - - /* - * If the controller is getting port events right after the reset, it - * means the initialization failed. Try resetting the controller again - * in such case. This is seen to happen after cold boot on DSR-1000N. - */ - usbc_gintsts.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_GINTSTS(usb->index)); - cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index), - usbc_gintsts.u32); - dev_dbg(dev, "gintsts after reset: 0x%x\n", (int)usbc_gintsts.u32); - if (!usbc_gintsts.s.disconnint && !usbc_gintsts.s.prtint) - return 0; - if (retries++ >= 5) - return -EAGAIN; - dev_info(dev, "controller reset failed (gintsts=0x%x) - retrying\n", - (int)usbc_gintsts.u32); - msleep(50); - cvmx_usb_shutdown(usb); - msleep(50); - goto retry; -} - -/** - * Reset a USB port. After this call succeeds, the USB port is - * online and servicing requests. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - */ -static void cvmx_usb_reset_port(struct octeon_hcd *usb) -{ - usb->usbcx_hprt.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HPRT(usb->index)); - - /* Program the port reset bit to start the reset process */ - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt, - prtrst, 1); - - /* - * Wait at least 50ms (high speed), or 10ms (full speed) for the reset - * process to complete. - */ - mdelay(50); - - /* Program the port reset bit to 0, USBC_HPRT[PRTRST] = 0 */ - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt, - prtrst, 0); - - /* - * Read the port speed field to get the enumerated speed, - * USBC_HPRT[PRTSPD]. - */ - usb->usbcx_hprt.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HPRT(usb->index)); -} - -/** - * Disable a USB port. After this call the USB port will not - * generate data transfers and will not generate events. - * Transactions in process will fail and call their - * associated callbacks. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * - * Returns: 0 or a negative error code. - */ -static int cvmx_usb_disable(struct octeon_hcd *usb) -{ - /* Disable the port */ - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt, - prtena, 1); - return 0; -} - -/** - * Get the current state of the USB port. Use this call to - * determine if the usb port has anything connected, is enabled, - * or has some sort of error condition. The return value of this - * call has "changed" bits to signal of the value of some fields - * have changed between calls. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * - * Returns: Port status information - */ -static struct cvmx_usb_port_status cvmx_usb_get_status(struct octeon_hcd *usb) -{ - union cvmx_usbcx_hprt usbc_hprt; - struct cvmx_usb_port_status result; - - memset(&result, 0, sizeof(result)); - - usbc_hprt.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); - result.port_enabled = usbc_hprt.s.prtena; - result.port_over_current = usbc_hprt.s.prtovrcurract; - result.port_powered = usbc_hprt.s.prtpwr; - result.port_speed = usbc_hprt.s.prtspd; - result.connected = usbc_hprt.s.prtconnsts; - result.connect_change = - result.connected != usb->port_status.connected; - - return result; -} - -/** - * Open a virtual pipe between the host and a USB device. A pipe - * must be opened before data can be transferred between a device - * and Octeon. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @device_addr: - * USB device address to open the pipe to - * (0-127). - * @endpoint_num: - * USB endpoint number to open the pipe to - * (0-15). - * @device_speed: - * The speed of the device the pipe is going - * to. This must match the device's speed, - * which may be different than the port speed. - * @max_packet: The maximum packet length the device can - * transmit/receive (low speed=0-8, full - * speed=0-1023, high speed=0-1024). This value - * comes from the standard endpoint descriptor - * field wMaxPacketSize bits <10:0>. - * @transfer_type: - * The type of transfer this pipe is for. - * @transfer_dir: - * The direction the pipe is in. This is not - * used for control pipes. - * @interval: For ISOCHRONOUS and INTERRUPT transfers, - * this is how often the transfer is scheduled - * for. All other transfers should specify - * zero. The units are in frames (8000/sec at - * high speed, 1000/sec for full speed). - * @multi_count: - * For high speed devices, this is the maximum - * allowed number of packet per microframe. - * Specify zero for non high speed devices. This - * value comes from the standard endpoint descriptor - * field wMaxPacketSize bits <12:11>. - * @hub_device_addr: - * Hub device address this device is connected - * to. Devices connected directly to Octeon - * use zero. This is only used when the device - * is full/low speed behind a high speed hub. - * The address will be of the high speed hub, - * not and full speed hubs after it. - * @hub_port: Which port on the hub the device is - * connected. Use zero for devices connected - * directly to Octeon. Like hub_device_addr, - * this is only used for full/low speed - * devices behind a high speed hub. - * - * Returns: A non-NULL value is a pipe. NULL means an error. - */ -static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct octeon_hcd *usb, - int device_addr, - int endpoint_num, - enum cvmx_usb_speed - device_speed, - int max_packet, - enum cvmx_usb_transfer - transfer_type, - enum cvmx_usb_direction - transfer_dir, - int interval, int multi_count, - int hub_device_addr, - int hub_port) -{ - struct cvmx_usb_pipe *pipe; - - pipe = kzalloc(sizeof(*pipe), GFP_ATOMIC); - if (!pipe) - return NULL; - if ((device_speed == CVMX_USB_SPEED_HIGH) && - (transfer_dir == CVMX_USB_DIRECTION_OUT) && - (transfer_type == CVMX_USB_TRANSFER_BULK)) - pipe->flags |= CVMX_USB_PIPE_FLAGS_NEED_PING; - pipe->device_addr = device_addr; - pipe->endpoint_num = endpoint_num; - pipe->device_speed = device_speed; - pipe->max_packet = max_packet; - pipe->transfer_type = transfer_type; - pipe->transfer_dir = transfer_dir; - INIT_LIST_HEAD(&pipe->transactions); - - /* - * All pipes use interval to rate limit NAK processing. Force an - * interval if one wasn't supplied - */ - if (!interval) - interval = 1; - if (cvmx_usb_pipe_needs_split(usb, pipe)) { - pipe->interval = interval * 8; - /* Force start splits to be schedule on uFrame 0 */ - pipe->next_tx_frame = ((usb->frame_number + 7) & ~7) + - pipe->interval; - } else { - pipe->interval = interval; - pipe->next_tx_frame = usb->frame_number + pipe->interval; - } - pipe->multi_count = multi_count; - pipe->hub_device_addr = hub_device_addr; - pipe->hub_port = hub_port; - pipe->pid_toggle = 0; - pipe->split_sc_frame = -1; - list_add_tail(&pipe->node, &usb->idle_pipes); - - /* - * We don't need to tell the hardware about this pipe yet since - * it doesn't have any submitted requests - */ - - return pipe; -} - -/** - * Poll the RX FIFOs and remove data as needed. This function is only used - * in non DMA mode. It is very important that this function be called quickly - * enough to prevent FIFO overflow. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - */ -static void cvmx_usb_poll_rx_fifo(struct octeon_hcd *usb) -{ - union cvmx_usbcx_grxstsph rx_status; - int channel; - int bytes; - u64 address; - u32 *ptr; - - rx_status.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_GRXSTSPH(usb->index)); - /* Only read data if IN data is there */ - if (rx_status.s.pktsts != 2) - return; - /* Check if no data is available */ - if (!rx_status.s.bcnt) - return; - - channel = rx_status.s.chnum; - bytes = rx_status.s.bcnt; - if (!bytes) - return; - - /* Get where the DMA engine would have written this data */ - address = cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index) + - channel * 8); - - ptr = cvmx_phys_to_ptr(address); - cvmx_write64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel * 8, - address + bytes); - - /* Loop writing the FIFO data for this packet into memory */ - while (bytes > 0) { - *ptr++ = cvmx_usb_read_csr32(usb, - USB_FIFO_ADDRESS(channel, usb->index)); - bytes -= 4; - } - CVMX_SYNCW; -} - -/** - * Fill the TX hardware fifo with data out of the software - * fifos - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @fifo: Software fifo to use - * @available: Amount of space in the hardware fifo - * - * Returns: Non zero if the hardware fifo was too small and needs - * to be serviced again. - */ -static int cvmx_usb_fill_tx_hw(struct octeon_hcd *usb, - struct cvmx_usb_tx_fifo *fifo, int available) -{ - /* - * We're done either when there isn't anymore space or the software FIFO - * is empty - */ - while (available && (fifo->head != fifo->tail)) { - int i = fifo->tail; - const u32 *ptr = cvmx_phys_to_ptr(fifo->entry[i].address); - u64 csr_address = USB_FIFO_ADDRESS(fifo->entry[i].channel, - usb->index) ^ 4; - int words = available; - - /* Limit the amount of data to what the SW fifo has */ - if (fifo->entry[i].size <= available) { - words = fifo->entry[i].size; - fifo->tail++; - if (fifo->tail > MAX_CHANNELS) - fifo->tail = 0; - } - - /* Update the next locations and counts */ - available -= words; - fifo->entry[i].address += words * 4; - fifo->entry[i].size -= words; - - /* - * Write the HW fifo data. The read every three writes is due - * to an errata on CN3XXX chips - */ - while (words > 3) { - cvmx_write64_uint32(csr_address, *ptr++); - cvmx_write64_uint32(csr_address, *ptr++); - cvmx_write64_uint32(csr_address, *ptr++); - cvmx_read64_uint64( - CVMX_USBNX_DMA0_INB_CHN0(usb->index)); - words -= 3; - } - cvmx_write64_uint32(csr_address, *ptr++); - if (--words) { - cvmx_write64_uint32(csr_address, *ptr++); - if (--words) - cvmx_write64_uint32(csr_address, *ptr++); - } - cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index)); - } - return fifo->head != fifo->tail; -} - -/** - * Check the hardware FIFOs and fill them as needed - * - * @usb: USB device state populated by cvmx_usb_initialize(). - */ -static void cvmx_usb_poll_tx_fifo(struct octeon_hcd *usb) -{ - if (usb->periodic.head != usb->periodic.tail) { - union cvmx_usbcx_hptxsts tx_status; - - tx_status.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HPTXSTS(usb->index)); - if (cvmx_usb_fill_tx_hw(usb, &usb->periodic, - tx_status.s.ptxfspcavail)) - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), - cvmx_usbcx_gintmsk, ptxfempmsk, 1); - else - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), - cvmx_usbcx_gintmsk, ptxfempmsk, 0); - } - - if (usb->nonperiodic.head != usb->nonperiodic.tail) { - union cvmx_usbcx_gnptxsts tx_status; - - tx_status.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_GNPTXSTS(usb->index)); - if (cvmx_usb_fill_tx_hw(usb, &usb->nonperiodic, - tx_status.s.nptxfspcavail)) - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), - cvmx_usbcx_gintmsk, nptxfempmsk, 1); - else - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), - cvmx_usbcx_gintmsk, nptxfempmsk, 0); - } -} - -/** - * Fill the TX FIFO with an outgoing packet - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @channel: Channel number to get packet from - */ -static void cvmx_usb_fill_tx_fifo(struct octeon_hcd *usb, int channel) -{ - union cvmx_usbcx_hccharx hcchar; - union cvmx_usbcx_hcspltx usbc_hcsplt; - union cvmx_usbcx_hctsizx usbc_hctsiz; - struct cvmx_usb_tx_fifo *fifo; - - /* We only need to fill data on outbound channels */ - hcchar.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HCCHARX(channel, usb->index)); - if (hcchar.s.epdir != CVMX_USB_DIRECTION_OUT) - return; - - /* OUT Splits only have data on the start and not the complete */ - usbc_hcsplt.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HCSPLTX(channel, usb->index)); - if (usbc_hcsplt.s.spltena && usbc_hcsplt.s.compsplt) - return; - - /* - * Find out how many bytes we need to fill and convert it into 32bit - * words. - */ - usbc_hctsiz.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HCTSIZX(channel, usb->index)); - if (!usbc_hctsiz.s.xfersize) - return; - - if ((hcchar.s.eptype == CVMX_USB_TRANSFER_INTERRUPT) || - (hcchar.s.eptype == CVMX_USB_TRANSFER_ISOCHRONOUS)) - fifo = &usb->periodic; - else - fifo = &usb->nonperiodic; - - fifo->entry[fifo->head].channel = channel; - fifo->entry[fifo->head].address = - cvmx_read64_uint64(CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + - channel * 8); - fifo->entry[fifo->head].size = (usbc_hctsiz.s.xfersize + 3) >> 2; - fifo->head++; - if (fifo->head > MAX_CHANNELS) - fifo->head = 0; - - cvmx_usb_poll_tx_fifo(usb); -} - -/** - * Perform channel specific setup for Control transactions. All - * the generic stuff will already have been done in cvmx_usb_start_channel(). - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @channel: Channel to setup - * @pipe: Pipe for control transaction - */ -static void cvmx_usb_start_channel_control(struct octeon_hcd *usb, - int channel, - struct cvmx_usb_pipe *pipe) -{ - struct usb_hcd *hcd = octeon_to_hcd(usb); - struct device *dev = hcd->self.controller; - struct cvmx_usb_transaction *transaction = - list_first_entry(&pipe->transactions, typeof(*transaction), - node); - struct usb_ctrlrequest *header = - cvmx_phys_to_ptr(transaction->control_header); - int bytes_to_transfer = transaction->buffer_length - - transaction->actual_bytes; - int packets_to_transfer; - union cvmx_usbcx_hctsizx usbc_hctsiz; - - usbc_hctsiz.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HCTSIZX(channel, usb->index)); - - switch (transaction->stage) { - case CVMX_USB_STAGE_NON_CONTROL: - case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE: - dev_err(dev, "%s: ERROR - Non control stage\n", __func__); - break; - case CVMX_USB_STAGE_SETUP: - usbc_hctsiz.s.pid = 3; /* Setup */ - bytes_to_transfer = sizeof(*header); - /* All Control operations start with a setup going OUT */ - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), - cvmx_usbcx_hccharx, epdir, - CVMX_USB_DIRECTION_OUT); - /* - * Setup send the control header instead of the buffer data. The - * buffer data will be used in the next stage - */ - cvmx_write64_uint64(CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + - channel * 8, - transaction->control_header); - break; - case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE: - usbc_hctsiz.s.pid = 3; /* Setup */ - bytes_to_transfer = 0; - /* All Control operations start with a setup going OUT */ - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), - cvmx_usbcx_hccharx, epdir, - CVMX_USB_DIRECTION_OUT); - - USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), - cvmx_usbcx_hcspltx, compsplt, 1); - break; - case CVMX_USB_STAGE_DATA: - usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe); - if (cvmx_usb_pipe_needs_split(usb, pipe)) { - if (header->bRequestType & USB_DIR_IN) - bytes_to_transfer = 0; - else if (bytes_to_transfer > pipe->max_packet) - bytes_to_transfer = pipe->max_packet; - } - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), - cvmx_usbcx_hccharx, epdir, - ((header->bRequestType & USB_DIR_IN) ? - CVMX_USB_DIRECTION_IN : - CVMX_USB_DIRECTION_OUT)); - break; - case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE: - usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe); - if (!(header->bRequestType & USB_DIR_IN)) - bytes_to_transfer = 0; - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), - cvmx_usbcx_hccharx, epdir, - ((header->bRequestType & USB_DIR_IN) ? - CVMX_USB_DIRECTION_IN : - CVMX_USB_DIRECTION_OUT)); - USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), - cvmx_usbcx_hcspltx, compsplt, 1); - break; - case CVMX_USB_STAGE_STATUS: - usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe); - bytes_to_transfer = 0; - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), - cvmx_usbcx_hccharx, epdir, - ((header->bRequestType & USB_DIR_IN) ? - CVMX_USB_DIRECTION_OUT : - CVMX_USB_DIRECTION_IN)); - break; - case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE: - usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe); - bytes_to_transfer = 0; - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), - cvmx_usbcx_hccharx, epdir, - ((header->bRequestType & USB_DIR_IN) ? - CVMX_USB_DIRECTION_OUT : - CVMX_USB_DIRECTION_IN)); - USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), - cvmx_usbcx_hcspltx, compsplt, 1); - break; - } - - /* - * Make sure the transfer never exceeds the byte limit of the hardware. - * Further bytes will be sent as continued transactions - */ - if (bytes_to_transfer > MAX_TRANSFER_BYTES) { - /* Round MAX_TRANSFER_BYTES to a multiple of out packet size */ - bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet; - bytes_to_transfer *= pipe->max_packet; - } - - /* - * Calculate the number of packets to transfer. If the length is zero - * we still need to transfer one packet - */ - packets_to_transfer = DIV_ROUND_UP(bytes_to_transfer, - pipe->max_packet); - if (packets_to_transfer == 0) { - packets_to_transfer = 1; - } else if ((packets_to_transfer > 1) && - (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) { - /* - * Limit to one packet when not using DMA. Channels must be - * restarted between every packet for IN transactions, so there - * is no reason to do multiple packets in a row - */ - packets_to_transfer = 1; - bytes_to_transfer = packets_to_transfer * pipe->max_packet; - } else if (packets_to_transfer > MAX_TRANSFER_PACKETS) { - /* - * Limit the number of packet and data transferred to what the - * hardware can handle - */ - packets_to_transfer = MAX_TRANSFER_PACKETS; - bytes_to_transfer = packets_to_transfer * pipe->max_packet; - } - - usbc_hctsiz.s.xfersize = bytes_to_transfer; - usbc_hctsiz.s.pktcnt = packets_to_transfer; - - cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), - usbc_hctsiz.u32); -} - -/** - * Start a channel to perform the pipe's head transaction - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @channel: Channel to setup - * @pipe: Pipe to start - */ -static void cvmx_usb_start_channel(struct octeon_hcd *usb, int channel, - struct cvmx_usb_pipe *pipe) -{ - struct cvmx_usb_transaction *transaction = - list_first_entry(&pipe->transactions, typeof(*transaction), - node); - - /* Make sure all writes to the DMA region get flushed */ - CVMX_SYNCW; - - /* Attach the channel to the pipe */ - usb->pipe_for_channel[channel] = pipe; - pipe->channel = channel; - pipe->flags |= CVMX_USB_PIPE_FLAGS_SCHEDULED; - - /* Mark this channel as in use */ - usb->idle_hardware_channels &= ~(1 << channel); - - /* Enable the channel interrupt bits */ - { - union cvmx_usbcx_hcintx usbc_hcint; - union cvmx_usbcx_hcintmskx usbc_hcintmsk; - union cvmx_usbcx_haintmsk usbc_haintmsk; - - /* Clear all channel status bits */ - usbc_hcint.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HCINTX(channel, usb->index)); - - cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCINTX(channel, usb->index), - usbc_hcint.u32); - - usbc_hcintmsk.u32 = 0; - usbc_hcintmsk.s.chhltdmsk = 1; - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) { - /* - * Channels need these extra interrupts when we aren't - * in DMA mode. - */ - usbc_hcintmsk.s.datatglerrmsk = 1; - usbc_hcintmsk.s.frmovrunmsk = 1; - usbc_hcintmsk.s.bblerrmsk = 1; - usbc_hcintmsk.s.xacterrmsk = 1; - if (cvmx_usb_pipe_needs_split(usb, pipe)) { - /* - * Splits don't generate xfercompl, so we need - * ACK and NYET. - */ - usbc_hcintmsk.s.nyetmsk = 1; - usbc_hcintmsk.s.ackmsk = 1; - } - usbc_hcintmsk.s.nakmsk = 1; - usbc_hcintmsk.s.stallmsk = 1; - usbc_hcintmsk.s.xfercomplmsk = 1; - } - cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCINTMSKX(channel, usb->index), - usbc_hcintmsk.u32); - - /* Enable the channel interrupt to propagate */ - usbc_haintmsk.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HAINTMSK(usb->index)); - usbc_haintmsk.s.haintmsk |= 1 << channel; - cvmx_usb_write_csr32(usb, CVMX_USBCX_HAINTMSK(usb->index), - usbc_haintmsk.u32); - } - - /* Setup the location the DMA engine uses. */ - { - u64 reg; - u64 dma_address = transaction->buffer + - transaction->actual_bytes; - - if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS) - dma_address = transaction->buffer + - transaction->iso_packets[0].offset + - transaction->actual_bytes; - - if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) - reg = CVMX_USBNX_DMA0_OUTB_CHN0(usb->index); - else - reg = CVMX_USBNX_DMA0_INB_CHN0(usb->index); - cvmx_write64_uint64(reg + channel * 8, dma_address); - } - - /* Setup both the size of the transfer and the SPLIT characteristics */ - { - union cvmx_usbcx_hcspltx usbc_hcsplt = {.u32 = 0}; - union cvmx_usbcx_hctsizx usbc_hctsiz = {.u32 = 0}; - int packets_to_transfer; - int bytes_to_transfer = transaction->buffer_length - - transaction->actual_bytes; - - /* - * ISOCHRONOUS transactions store each individual transfer size - * in the packet structure, not the global buffer_length - */ - if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS) - bytes_to_transfer = - transaction->iso_packets[0].length - - transaction->actual_bytes; - - /* - * We need to do split transactions when we are talking to non - * high speed devices that are behind a high speed hub - */ - if (cvmx_usb_pipe_needs_split(usb, pipe)) { - /* - * On the start split phase (stage is even) record the - * frame number we will need to send the split complete. - * We only store the lower two bits since the time ahead - * can only be two frames - */ - if ((transaction->stage & 1) == 0) { - if (transaction->type == CVMX_USB_TRANSFER_BULK) - pipe->split_sc_frame = - (usb->frame_number + 1) & 0x7f; - else - pipe->split_sc_frame = - (usb->frame_number + 2) & 0x7f; - } else { - pipe->split_sc_frame = -1; - } - - usbc_hcsplt.s.spltena = 1; - usbc_hcsplt.s.hubaddr = pipe->hub_device_addr; - usbc_hcsplt.s.prtaddr = pipe->hub_port; - usbc_hcsplt.s.compsplt = (transaction->stage == - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE); - - /* - * SPLIT transactions can only ever transmit one data - * packet so limit the transfer size to the max packet - * size - */ - if (bytes_to_transfer > pipe->max_packet) - bytes_to_transfer = pipe->max_packet; - - /* - * ISOCHRONOUS OUT splits are unique in that they limit - * data transfers to 188 byte chunks representing the - * begin/middle/end of the data or all - */ - if (!usbc_hcsplt.s.compsplt && - (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) && - (pipe->transfer_type == - CVMX_USB_TRANSFER_ISOCHRONOUS)) { - /* - * Clear the split complete frame number as - * there isn't going to be a split complete - */ - pipe->split_sc_frame = -1; - /* - * See if we've started this transfer and sent - * data - */ - if (transaction->actual_bytes == 0) { - /* - * Nothing sent yet, this is either a - * begin or the entire payload - */ - if (bytes_to_transfer <= 188) - /* Entire payload in one go */ - usbc_hcsplt.s.xactpos = 3; - else - /* First part of payload */ - usbc_hcsplt.s.xactpos = 2; - } else { - /* - * Continuing the previous data, we must - * either be in the middle or at the end - */ - if (bytes_to_transfer <= 188) - /* End of payload */ - usbc_hcsplt.s.xactpos = 1; - else - /* Middle of payload */ - usbc_hcsplt.s.xactpos = 0; - } - /* - * Again, the transfer size is limited to 188 - * bytes - */ - if (bytes_to_transfer > 188) - bytes_to_transfer = 188; - } - } - - /* - * Make sure the transfer never exceeds the byte limit of the - * hardware. Further bytes will be sent as continued - * transactions - */ - if (bytes_to_transfer > MAX_TRANSFER_BYTES) { - /* - * Round MAX_TRANSFER_BYTES to a multiple of out packet - * size - */ - bytes_to_transfer = MAX_TRANSFER_BYTES / - pipe->max_packet; - bytes_to_transfer *= pipe->max_packet; - } - - /* - * Calculate the number of packets to transfer. If the length is - * zero we still need to transfer one packet - */ - packets_to_transfer = - DIV_ROUND_UP(bytes_to_transfer, pipe->max_packet); - if (packets_to_transfer == 0) { - packets_to_transfer = 1; - } else if ((packets_to_transfer > 1) && - (usb->init_flags & - CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) { - /* - * Limit to one packet when not using DMA. Channels must - * be restarted between every packet for IN - * transactions, so there is no reason to do multiple - * packets in a row - */ - packets_to_transfer = 1; - bytes_to_transfer = packets_to_transfer * - pipe->max_packet; - } else if (packets_to_transfer > MAX_TRANSFER_PACKETS) { - /* - * Limit the number of packet and data transferred to - * what the hardware can handle - */ - packets_to_transfer = MAX_TRANSFER_PACKETS; - bytes_to_transfer = packets_to_transfer * - pipe->max_packet; - } - - usbc_hctsiz.s.xfersize = bytes_to_transfer; - usbc_hctsiz.s.pktcnt = packets_to_transfer; - - /* Update the DATA0/DATA1 toggle */ - usbc_hctsiz.s.pid = cvmx_usb_get_data_pid(pipe); - /* - * High speed pipes may need a hardware ping before they start - */ - if (pipe->flags & CVMX_USB_PIPE_FLAGS_NEED_PING) - usbc_hctsiz.s.dopng = 1; - - cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCSPLTX(channel, usb->index), - usbc_hcsplt.u32); - cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCTSIZX(channel, usb->index), - usbc_hctsiz.u32); - } - - /* Setup the Host Channel Characteristics Register */ - { - union cvmx_usbcx_hccharx usbc_hcchar = {.u32 = 0}; - - /* - * Set the startframe odd/even properly. This is only used for - * periodic - */ - usbc_hcchar.s.oddfrm = usb->frame_number & 1; - - /* - * Set the number of back to back packets allowed by this - * endpoint. Split transactions interpret "ec" as the number of - * immediate retries of failure. These retries happen too - * quickly, so we disable these entirely for splits - */ - if (cvmx_usb_pipe_needs_split(usb, pipe)) - usbc_hcchar.s.ec = 1; - else if (pipe->multi_count < 1) - usbc_hcchar.s.ec = 1; - else if (pipe->multi_count > 3) - usbc_hcchar.s.ec = 3; - else - usbc_hcchar.s.ec = pipe->multi_count; - - /* Set the rest of the endpoint specific settings */ - usbc_hcchar.s.devaddr = pipe->device_addr; - usbc_hcchar.s.eptype = transaction->type; - usbc_hcchar.s.lspddev = - (pipe->device_speed == CVMX_USB_SPEED_LOW); - usbc_hcchar.s.epdir = pipe->transfer_dir; - usbc_hcchar.s.epnum = pipe->endpoint_num; - usbc_hcchar.s.mps = pipe->max_packet; - cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCCHARX(channel, usb->index), - usbc_hcchar.u32); - } - - /* Do transaction type specific fixups as needed */ - switch (transaction->type) { - case CVMX_USB_TRANSFER_CONTROL: - cvmx_usb_start_channel_control(usb, channel, pipe); - break; - case CVMX_USB_TRANSFER_BULK: - case CVMX_USB_TRANSFER_INTERRUPT: - break; - case CVMX_USB_TRANSFER_ISOCHRONOUS: - if (!cvmx_usb_pipe_needs_split(usb, pipe)) { - /* - * ISO transactions require different PIDs depending on - * direction and how many packets are needed - */ - if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) { - if (pipe->multi_count < 2) /* Need DATA0 */ - USB_SET_FIELD32( - CVMX_USBCX_HCTSIZX(channel, - usb->index), - cvmx_usbcx_hctsizx, pid, 0); - else /* Need MDATA */ - USB_SET_FIELD32( - CVMX_USBCX_HCTSIZX(channel, - usb->index), - cvmx_usbcx_hctsizx, pid, 3); - } - } - break; - } - { - union cvmx_usbcx_hctsizx usbc_hctsiz = { .u32 = - cvmx_usb_read_csr32(usb, - CVMX_USBCX_HCTSIZX(channel, - usb->index)) - }; - transaction->xfersize = usbc_hctsiz.s.xfersize; - transaction->pktcnt = usbc_hctsiz.s.pktcnt; - } - /* Remember when we start a split transaction */ - if (cvmx_usb_pipe_needs_split(usb, pipe)) - usb->active_split = transaction; - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), - cvmx_usbcx_hccharx, chena, 1); - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) - cvmx_usb_fill_tx_fifo(usb, channel); -} - -/** - * Find a pipe that is ready to be scheduled to hardware. - * @usb: USB device state populated by cvmx_usb_initialize(). - * @xfer_type: Transfer type - * - * Returns: Pipe or NULL if none are ready - */ -static struct cvmx_usb_pipe *cvmx_usb_find_ready_pipe(struct octeon_hcd *usb, - enum cvmx_usb_transfer xfer_type) -{ - struct list_head *list = usb->active_pipes + xfer_type; - u64 current_frame = usb->frame_number; - struct cvmx_usb_pipe *pipe; - - list_for_each_entry(pipe, list, node) { - struct cvmx_usb_transaction *t = - list_first_entry(&pipe->transactions, typeof(*t), - node); - if (!(pipe->flags & CVMX_USB_PIPE_FLAGS_SCHEDULED) && t && - (pipe->next_tx_frame <= current_frame) && - ((pipe->split_sc_frame == -1) || - ((((int)current_frame - pipe->split_sc_frame) & 0x7f) < - 0x40)) && - (!usb->active_split || (usb->active_split == t))) { - prefetch(t); - return pipe; - } - } - return NULL; -} - -static struct cvmx_usb_pipe *cvmx_usb_next_pipe(struct octeon_hcd *usb, - int is_sof) -{ - struct cvmx_usb_pipe *pipe; - - /* Find a pipe needing service. */ - if (is_sof) { - /* - * Only process periodic pipes on SOF interrupts. This way we - * are sure that the periodic data is sent in the beginning of - * the frame. - */ - pipe = cvmx_usb_find_ready_pipe(usb, - CVMX_USB_TRANSFER_ISOCHRONOUS); - if (pipe) - return pipe; - pipe = cvmx_usb_find_ready_pipe(usb, - CVMX_USB_TRANSFER_INTERRUPT); - if (pipe) - return pipe; - } - pipe = cvmx_usb_find_ready_pipe(usb, CVMX_USB_TRANSFER_CONTROL); - if (pipe) - return pipe; - return cvmx_usb_find_ready_pipe(usb, CVMX_USB_TRANSFER_BULK); -} - -/** - * Called whenever a pipe might need to be scheduled to the - * hardware. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @is_sof: True if this schedule was called on a SOF interrupt. - */ -static void cvmx_usb_schedule(struct octeon_hcd *usb, int is_sof) -{ - int channel; - struct cvmx_usb_pipe *pipe; - int need_sof; - enum cvmx_usb_transfer ttype; - - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) { - /* - * Without DMA we need to be careful to not schedule something - * at the end of a frame and cause an overrun. - */ - union cvmx_usbcx_hfnum hfnum = { - .u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HFNUM(usb->index)) - }; - - union cvmx_usbcx_hfir hfir = { - .u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HFIR(usb->index)) - }; - - if (hfnum.s.frrem < hfir.s.frint / 4) - goto done; - } - - while (usb->idle_hardware_channels) { - /* Find an idle channel */ - channel = __fls(usb->idle_hardware_channels); - if (unlikely(channel > 7)) - break; - - pipe = cvmx_usb_next_pipe(usb, is_sof); - if (!pipe) - break; - - cvmx_usb_start_channel(usb, channel, pipe); - } - -done: - /* - * Only enable SOF interrupts when we have transactions pending in the - * future that might need to be scheduled - */ - need_sof = 0; - for (ttype = CVMX_USB_TRANSFER_CONTROL; - ttype <= CVMX_USB_TRANSFER_INTERRUPT; ttype++) { - list_for_each_entry(pipe, &usb->active_pipes[ttype], node) { - if (pipe->next_tx_frame > usb->frame_number) { - need_sof = 1; - break; - } - } - } - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), - cvmx_usbcx_gintmsk, sofmsk, need_sof); -} - -static void octeon_usb_urb_complete_callback(struct octeon_hcd *usb, - enum cvmx_usb_status status, - struct cvmx_usb_pipe *pipe, - struct cvmx_usb_transaction - *transaction, - int bytes_transferred, - struct urb *urb) -{ - struct usb_hcd *hcd = octeon_to_hcd(usb); - struct device *dev = hcd->self.controller; - - if (likely(status == CVMX_USB_STATUS_OK)) - urb->actual_length = bytes_transferred; - else - urb->actual_length = 0; - - urb->hcpriv = NULL; - - /* For Isochronous transactions we need to update the URB packet status - * list from data in our private copy - */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - int i; - /* - * The pointer to the private list is stored in the setup_packet - * field. - */ - struct cvmx_usb_iso_packet *iso_packet = - (struct cvmx_usb_iso_packet *)urb->setup_packet; - /* Recalculate the transfer size by adding up each packet */ - urb->actual_length = 0; - for (i = 0; i < urb->number_of_packets; i++) { - if (iso_packet[i].status == CVMX_USB_STATUS_OK) { - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = - iso_packet[i].length; - urb->actual_length += - urb->iso_frame_desc[i].actual_length; - } else { - dev_dbg(dev, "ISOCHRONOUS packet=%d of %d status=%d pipe=%p transaction=%p size=%d\n", - i, urb->number_of_packets, - iso_packet[i].status, pipe, - transaction, iso_packet[i].length); - urb->iso_frame_desc[i].status = -EREMOTEIO; - } - } - /* Free the private list now that we don't need it anymore */ - kfree(iso_packet); - urb->setup_packet = NULL; - } - - switch (status) { - case CVMX_USB_STATUS_OK: - urb->status = 0; - break; - case CVMX_USB_STATUS_CANCEL: - if (urb->status == 0) - urb->status = -ENOENT; - break; - case CVMX_USB_STATUS_STALL: - dev_dbg(dev, "status=stall pipe=%p transaction=%p size=%d\n", - pipe, transaction, bytes_transferred); - urb->status = -EPIPE; - break; - case CVMX_USB_STATUS_BABBLEERR: - dev_dbg(dev, "status=babble pipe=%p transaction=%p size=%d\n", - pipe, transaction, bytes_transferred); - urb->status = -EPIPE; - break; - case CVMX_USB_STATUS_SHORT: - dev_dbg(dev, "status=short pipe=%p transaction=%p size=%d\n", - pipe, transaction, bytes_transferred); - urb->status = -EREMOTEIO; - break; - case CVMX_USB_STATUS_ERROR: - case CVMX_USB_STATUS_XACTERR: - case CVMX_USB_STATUS_DATATGLERR: - case CVMX_USB_STATUS_FRAMEERR: - dev_dbg(dev, "status=%d pipe=%p transaction=%p size=%d\n", - status, pipe, transaction, bytes_transferred); - urb->status = -EPROTO; - break; - } - usb_hcd_unlink_urb_from_ep(octeon_to_hcd(usb), urb); - spin_unlock(&usb->lock); - usb_hcd_giveback_urb(octeon_to_hcd(usb), urb, urb->status); - spin_lock(&usb->lock); -} - -/** - * Signal the completion of a transaction and free it. The - * transaction will be removed from the pipe transaction list. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @pipe: Pipe the transaction is on - * @transaction: - * Transaction that completed - * @complete_code: - * Completion code - */ -static void cvmx_usb_complete(struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe, - struct cvmx_usb_transaction *transaction, - enum cvmx_usb_status complete_code) -{ - /* If this was a split then clear our split in progress marker */ - if (usb->active_split == transaction) - usb->active_split = NULL; - - /* - * Isochronous transactions need extra processing as they might not be - * done after a single data transfer - */ - if (unlikely(transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)) { - /* Update the number of bytes transferred in this ISO packet */ - transaction->iso_packets[0].length = transaction->actual_bytes; - transaction->iso_packets[0].status = complete_code; - - /* - * If there are more ISOs pending and we succeeded, schedule the - * next one - */ - if ((transaction->iso_number_packets > 1) && - (complete_code == CVMX_USB_STATUS_OK)) { - /* No bytes transferred for this packet as of yet */ - transaction->actual_bytes = 0; - /* One less ISO waiting to transfer */ - transaction->iso_number_packets--; - /* Increment to the next location in our packet array */ - transaction->iso_packets++; - transaction->stage = CVMX_USB_STAGE_NON_CONTROL; - return; - } - } - - /* Remove the transaction from the pipe list */ - list_del(&transaction->node); - if (list_empty(&pipe->transactions)) - list_move_tail(&pipe->node, &usb->idle_pipes); - octeon_usb_urb_complete_callback(usb, complete_code, pipe, - transaction, - transaction->actual_bytes, - transaction->urb); - kfree(transaction); -} - -/** - * Submit a usb transaction to a pipe. Called for all types - * of transactions. - * - * @usb: - * @pipe: Which pipe to submit to. - * @type: Transaction type - * @buffer: User buffer for the transaction - * @buffer_length: - * User buffer's length in bytes - * @control_header: - * For control transactions, the 8 byte standard header - * @iso_start_frame: - * For ISO transactions, the start frame - * @iso_number_packets: - * For ISO, the number of packet in the transaction. - * @iso_packets: - * A description of each ISO packet - * @urb: URB for the callback - * - * Returns: Transaction or NULL on failure. - */ -static struct cvmx_usb_transaction *cvmx_usb_submit_transaction( - struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe, - enum cvmx_usb_transfer type, - u64 buffer, - int buffer_length, - u64 control_header, - int iso_start_frame, - int iso_number_packets, - struct cvmx_usb_iso_packet *iso_packets, - struct urb *urb) -{ - struct cvmx_usb_transaction *transaction; - - if (unlikely(pipe->transfer_type != type)) - return NULL; - - transaction = kzalloc(sizeof(*transaction), GFP_ATOMIC); - if (unlikely(!transaction)) - return NULL; - - transaction->type = type; - transaction->buffer = buffer; - transaction->buffer_length = buffer_length; - transaction->control_header = control_header; - /* FIXME: This is not used, implement it. */ - transaction->iso_start_frame = iso_start_frame; - transaction->iso_number_packets = iso_number_packets; - transaction->iso_packets = iso_packets; - transaction->urb = urb; - if (transaction->type == CVMX_USB_TRANSFER_CONTROL) - transaction->stage = CVMX_USB_STAGE_SETUP; - else - transaction->stage = CVMX_USB_STAGE_NON_CONTROL; - - if (!list_empty(&pipe->transactions)) { - list_add_tail(&transaction->node, &pipe->transactions); - } else { - list_add_tail(&transaction->node, &pipe->transactions); - list_move_tail(&pipe->node, - &usb->active_pipes[pipe->transfer_type]); - - /* - * We may need to schedule the pipe if this was the head of the - * pipe. - */ - cvmx_usb_schedule(usb, 0); - } - - return transaction; -} - -/** - * Call to submit a USB Bulk transfer to a pipe. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @pipe: Handle to the pipe for the transfer. - * @urb: URB. - * - * Returns: A submitted transaction or NULL on failure. - */ -static struct cvmx_usb_transaction *cvmx_usb_submit_bulk( - struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe, - struct urb *urb) -{ - return cvmx_usb_submit_transaction(usb, pipe, CVMX_USB_TRANSFER_BULK, - urb->transfer_dma, - urb->transfer_buffer_length, - 0, /* control_header */ - 0, /* iso_start_frame */ - 0, /* iso_number_packets */ - NULL, /* iso_packets */ - urb); -} - -/** - * Call to submit a USB Interrupt transfer to a pipe. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @pipe: Handle to the pipe for the transfer. - * @urb: URB returned when the callback is called. - * - * Returns: A submitted transaction or NULL on failure. - */ -static struct cvmx_usb_transaction *cvmx_usb_submit_interrupt( - struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe, - struct urb *urb) -{ - return cvmx_usb_submit_transaction(usb, pipe, - CVMX_USB_TRANSFER_INTERRUPT, - urb->transfer_dma, - urb->transfer_buffer_length, - 0, /* control_header */ - 0, /* iso_start_frame */ - 0, /* iso_number_packets */ - NULL, /* iso_packets */ - urb); -} - -/** - * Call to submit a USB Control transfer to a pipe. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @pipe: Handle to the pipe for the transfer. - * @urb: URB. - * - * Returns: A submitted transaction or NULL on failure. - */ -static struct cvmx_usb_transaction *cvmx_usb_submit_control( - struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe, - struct urb *urb) -{ - int buffer_length = urb->transfer_buffer_length; - u64 control_header = urb->setup_dma; - struct usb_ctrlrequest *header = cvmx_phys_to_ptr(control_header); - - if ((header->bRequestType & USB_DIR_IN) == 0) - buffer_length = le16_to_cpu(header->wLength); - - return cvmx_usb_submit_transaction(usb, pipe, - CVMX_USB_TRANSFER_CONTROL, - urb->transfer_dma, buffer_length, - control_header, - 0, /* iso_start_frame */ - 0, /* iso_number_packets */ - NULL, /* iso_packets */ - urb); -} - -/** - * Call to submit a USB Isochronous transfer to a pipe. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @pipe: Handle to the pipe for the transfer. - * @urb: URB returned when the callback is called. - * - * Returns: A submitted transaction or NULL on failure. - */ -static struct cvmx_usb_transaction *cvmx_usb_submit_isochronous( - struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe, - struct urb *urb) -{ - struct cvmx_usb_iso_packet *packets; - - packets = (struct cvmx_usb_iso_packet *)urb->setup_packet; - return cvmx_usb_submit_transaction(usb, pipe, - CVMX_USB_TRANSFER_ISOCHRONOUS, - urb->transfer_dma, - urb->transfer_buffer_length, - 0, /* control_header */ - urb->start_frame, - urb->number_of_packets, - packets, urb); -} - -/** - * Cancel one outstanding request in a pipe. Canceling a request - * can fail if the transaction has already completed before cancel - * is called. Even after a successful cancel call, it may take - * a frame or two for the cvmx_usb_poll() function to call the - * associated callback. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @pipe: Pipe to cancel requests in. - * @transaction: Transaction to cancel, returned by the submit function. - * - * Returns: 0 or a negative error code. - */ -static int cvmx_usb_cancel(struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe, - struct cvmx_usb_transaction *transaction) -{ - /* - * If the transaction is the HEAD of the queue and scheduled. We need to - * treat it special - */ - if (list_first_entry(&pipe->transactions, typeof(*transaction), node) == - transaction && (pipe->flags & CVMX_USB_PIPE_FLAGS_SCHEDULED)) { - union cvmx_usbcx_hccharx usbc_hcchar; - - usb->pipe_for_channel[pipe->channel] = NULL; - pipe->flags &= ~CVMX_USB_PIPE_FLAGS_SCHEDULED; - - CVMX_SYNCW; - - usbc_hcchar.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HCCHARX(pipe->channel, usb->index)); - /* - * If the channel isn't enabled then the transaction already - * completed. - */ - if (usbc_hcchar.s.chena) { - usbc_hcchar.s.chdis = 1; - cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCCHARX(pipe->channel, - usb->index), - usbc_hcchar.u32); - } - } - cvmx_usb_complete(usb, pipe, transaction, CVMX_USB_STATUS_CANCEL); - return 0; -} - -/** - * Cancel all outstanding requests in a pipe. Logically all this - * does is call cvmx_usb_cancel() in a loop. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @pipe: Pipe to cancel requests in. - * - * Returns: 0 or a negative error code. - */ -static int cvmx_usb_cancel_all(struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe) -{ - struct cvmx_usb_transaction *transaction, *next; - - /* Simply loop through and attempt to cancel each transaction */ - list_for_each_entry_safe(transaction, next, &pipe->transactions, node) { - int result = cvmx_usb_cancel(usb, pipe, transaction); - - if (unlikely(result != 0)) - return result; - } - return 0; -} - -/** - * Close a pipe created with cvmx_usb_open_pipe(). - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * @pipe: Pipe to close. - * - * Returns: 0 or a negative error code. EBUSY is returned if the pipe has - * outstanding transfers. - */ -static int cvmx_usb_close_pipe(struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe) -{ - /* Fail if the pipe has pending transactions */ - if (!list_empty(&pipe->transactions)) - return -EBUSY; - - list_del(&pipe->node); - kfree(pipe); - - return 0; -} - -/** - * Get the current USB protocol level frame number. The frame - * number is always in the range of 0-0x7ff. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * - * Returns: USB frame number - */ -static int cvmx_usb_get_frame_number(struct octeon_hcd *usb) -{ - union cvmx_usbcx_hfnum usbc_hfnum; - - usbc_hfnum.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index)); - - return usbc_hfnum.s.frnum; -} - -static void cvmx_usb_transfer_control(struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe, - struct cvmx_usb_transaction *transaction, - union cvmx_usbcx_hccharx usbc_hcchar, - int buffer_space_left, - int bytes_in_last_packet) -{ - switch (transaction->stage) { - case CVMX_USB_STAGE_NON_CONTROL: - case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE: - /* This should be impossible */ - cvmx_usb_complete(usb, pipe, transaction, - CVMX_USB_STATUS_ERROR); - break; - case CVMX_USB_STAGE_SETUP: - pipe->pid_toggle = 1; - if (cvmx_usb_pipe_needs_split(usb, pipe)) { - transaction->stage = - CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE; - } else { - struct usb_ctrlrequest *header = - cvmx_phys_to_ptr(transaction->control_header); - if (header->wLength) - transaction->stage = CVMX_USB_STAGE_DATA; - else - transaction->stage = CVMX_USB_STAGE_STATUS; - } - break; - case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE: - { - struct usb_ctrlrequest *header = - cvmx_phys_to_ptr(transaction->control_header); - if (header->wLength) - transaction->stage = CVMX_USB_STAGE_DATA; - else - transaction->stage = CVMX_USB_STAGE_STATUS; - } - break; - case CVMX_USB_STAGE_DATA: - if (cvmx_usb_pipe_needs_split(usb, pipe)) { - transaction->stage = CVMX_USB_STAGE_DATA_SPLIT_COMPLETE; - /* - * For setup OUT data that are splits, - * the hardware doesn't appear to count - * transferred data. Here we manually - * update the data transferred - */ - if (!usbc_hcchar.s.epdir) { - if (buffer_space_left < pipe->max_packet) - transaction->actual_bytes += - buffer_space_left; - else - transaction->actual_bytes += - pipe->max_packet; - } - } else if ((buffer_space_left == 0) || - (bytes_in_last_packet < pipe->max_packet)) { - pipe->pid_toggle = 1; - transaction->stage = CVMX_USB_STAGE_STATUS; - } - break; - case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE: - if ((buffer_space_left == 0) || - (bytes_in_last_packet < pipe->max_packet)) { - pipe->pid_toggle = 1; - transaction->stage = CVMX_USB_STAGE_STATUS; - } else { - transaction->stage = CVMX_USB_STAGE_DATA; - } - break; - case CVMX_USB_STAGE_STATUS: - if (cvmx_usb_pipe_needs_split(usb, pipe)) - transaction->stage = - CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE; - else - cvmx_usb_complete(usb, pipe, transaction, - CVMX_USB_STATUS_OK); - break; - case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE: - cvmx_usb_complete(usb, pipe, transaction, CVMX_USB_STATUS_OK); - break; - } -} - -static void cvmx_usb_transfer_bulk(struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe, - struct cvmx_usb_transaction *transaction, - union cvmx_usbcx_hcintx usbc_hcint, - int buffer_space_left, - int bytes_in_last_packet) -{ - /* - * The only time a bulk transfer isn't complete when it finishes with - * an ACK is during a split transaction. For splits we need to continue - * the transfer if more data is needed. - */ - if (cvmx_usb_pipe_needs_split(usb, pipe)) { - if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL) - transaction->stage = - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE; - else if (buffer_space_left && - (bytes_in_last_packet == pipe->max_packet)) - transaction->stage = CVMX_USB_STAGE_NON_CONTROL; - else - cvmx_usb_complete(usb, pipe, transaction, - CVMX_USB_STATUS_OK); - } else { - if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) && - (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) && - (usbc_hcint.s.nak)) - pipe->flags |= CVMX_USB_PIPE_FLAGS_NEED_PING; - if (!buffer_space_left || - (bytes_in_last_packet < pipe->max_packet)) - cvmx_usb_complete(usb, pipe, transaction, - CVMX_USB_STATUS_OK); - } -} - -static void cvmx_usb_transfer_intr(struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe, - struct cvmx_usb_transaction *transaction, - int buffer_space_left, - int bytes_in_last_packet) -{ - if (cvmx_usb_pipe_needs_split(usb, pipe)) { - if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL) { - transaction->stage = - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE; - } else if (buffer_space_left && - (bytes_in_last_packet == pipe->max_packet)) { - transaction->stage = CVMX_USB_STAGE_NON_CONTROL; - } else { - pipe->next_tx_frame += pipe->interval; - cvmx_usb_complete(usb, pipe, transaction, - CVMX_USB_STATUS_OK); - } - } else if (!buffer_space_left || - (bytes_in_last_packet < pipe->max_packet)) { - pipe->next_tx_frame += pipe->interval; - cvmx_usb_complete(usb, pipe, transaction, CVMX_USB_STATUS_OK); - } -} - -static void cvmx_usb_transfer_isoc(struct octeon_hcd *usb, - struct cvmx_usb_pipe *pipe, - struct cvmx_usb_transaction *transaction, - int buffer_space_left, - int bytes_in_last_packet, - int bytes_this_transfer) -{ - if (cvmx_usb_pipe_needs_split(usb, pipe)) { - /* - * ISOCHRONOUS OUT splits don't require a complete split stage. - * Instead they use a sequence of begin OUT splits to transfer - * the data 188 bytes at a time. Once the transfer is complete, - * the pipe sleeps until the next schedule interval. - */ - if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) { - /* - * If no space left or this wasn't a max size packet - * then this transfer is complete. Otherwise start it - * again to send the next 188 bytes - */ - if (!buffer_space_left || (bytes_this_transfer < 188)) { - pipe->next_tx_frame += pipe->interval; - cvmx_usb_complete(usb, pipe, transaction, - CVMX_USB_STATUS_OK); - } - return; - } - if (transaction->stage == - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE) { - /* - * We are in the incoming data phase. Keep getting data - * until we run out of space or get a small packet - */ - if ((buffer_space_left == 0) || - (bytes_in_last_packet < pipe->max_packet)) { - pipe->next_tx_frame += pipe->interval; - cvmx_usb_complete(usb, pipe, transaction, - CVMX_USB_STATUS_OK); - } - } else { - transaction->stage = - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE; - } - } else { - pipe->next_tx_frame += pipe->interval; - cvmx_usb_complete(usb, pipe, transaction, CVMX_USB_STATUS_OK); - } -} - -/** - * Poll a channel for status - * - * @usb: USB device - * @channel: Channel to poll - * - * Returns: Zero on success - */ -static int cvmx_usb_poll_channel(struct octeon_hcd *usb, int channel) -{ - struct usb_hcd *hcd = octeon_to_hcd(usb); - struct device *dev = hcd->self.controller; - union cvmx_usbcx_hcintx usbc_hcint; - union cvmx_usbcx_hctsizx usbc_hctsiz; - union cvmx_usbcx_hccharx usbc_hcchar; - struct cvmx_usb_pipe *pipe; - struct cvmx_usb_transaction *transaction; - int bytes_this_transfer; - int bytes_in_last_packet; - int packets_processed; - int buffer_space_left; - - /* Read the interrupt status bits for the channel */ - usbc_hcint.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HCINTX(channel, usb->index)); - - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) { - usbc_hcchar.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HCCHARX(channel, usb->index)); - - if (usbc_hcchar.s.chena && usbc_hcchar.s.chdis) { - /* - * There seems to be a bug in CN31XX which can cause - * interrupt IN transfers to get stuck until we do a - * write of HCCHARX without changing things - */ - cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCCHARX(channel, - usb->index), - usbc_hcchar.u32); - return 0; - } - - /* - * In non DMA mode the channels don't halt themselves. We need - * to manually disable channels that are left running - */ - if (!usbc_hcint.s.chhltd) { - if (usbc_hcchar.s.chena) { - union cvmx_usbcx_hcintmskx hcintmsk; - /* Disable all interrupts except CHHLTD */ - hcintmsk.u32 = 0; - hcintmsk.s.chhltdmsk = 1; - cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCINTMSKX(channel, usb->index), - hcintmsk.u32); - usbc_hcchar.s.chdis = 1; - cvmx_usb_write_csr32(usb, - CVMX_USBCX_HCCHARX(channel, usb->index), - usbc_hcchar.u32); - return 0; - } else if (usbc_hcint.s.xfercompl) { - /* - * Successful IN/OUT with transfer complete. - * Channel halt isn't needed. - */ - } else { - dev_err(dev, "USB%d: Channel %d interrupt without halt\n", - usb->index, channel); - return 0; - } - } - } else { - /* - * There is are no interrupts that we need to process when the - * channel is still running - */ - if (!usbc_hcint.s.chhltd) - return 0; - } - - /* Disable the channel interrupts now that it is done */ - cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0); - usb->idle_hardware_channels |= (1 << channel); - - /* Make sure this channel is tied to a valid pipe */ - pipe = usb->pipe_for_channel[channel]; - prefetch(pipe); - if (!pipe) - return 0; - transaction = list_first_entry(&pipe->transactions, - typeof(*transaction), - node); - prefetch(transaction); - - /* - * Disconnect this pipe from the HW channel. Later the schedule - * function will figure out which pipe needs to go - */ - usb->pipe_for_channel[channel] = NULL; - pipe->flags &= ~CVMX_USB_PIPE_FLAGS_SCHEDULED; - - /* - * Read the channel config info so we can figure out how much data - * transferred - */ - usbc_hcchar.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HCCHARX(channel, usb->index)); - usbc_hctsiz.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HCTSIZX(channel, usb->index)); - - /* - * Calculating the number of bytes successfully transferred is dependent - * on the transfer direction - */ - packets_processed = transaction->pktcnt - usbc_hctsiz.s.pktcnt; - if (usbc_hcchar.s.epdir) { - /* - * IN transactions are easy. For every byte received the - * hardware decrements xfersize. All we need to do is subtract - * the current value of xfersize from its starting value and we - * know how many bytes were written to the buffer - */ - bytes_this_transfer = transaction->xfersize - - usbc_hctsiz.s.xfersize; - } else { - /* - * OUT transaction don't decrement xfersize. Instead pktcnt is - * decremented on every successful packet send. The hardware - * does this when it receives an ACK, or NYET. If it doesn't - * receive one of these responses pktcnt doesn't change - */ - bytes_this_transfer = packets_processed * usbc_hcchar.s.mps; - /* - * The last packet may not be a full transfer if we didn't have - * enough data - */ - if (bytes_this_transfer > transaction->xfersize) - bytes_this_transfer = transaction->xfersize; - } - /* Figure out how many bytes were in the last packet of the transfer */ - if (packets_processed) - bytes_in_last_packet = bytes_this_transfer - - (packets_processed - 1) * usbc_hcchar.s.mps; - else - bytes_in_last_packet = bytes_this_transfer; - - /* - * As a special case, setup transactions output the setup header, not - * the user's data. For this reason we don't count setup data as bytes - * transferred - */ - if ((transaction->stage == CVMX_USB_STAGE_SETUP) || - (transaction->stage == CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE)) - bytes_this_transfer = 0; - - /* - * Add the bytes transferred to the running total. It is important that - * bytes_this_transfer doesn't count any data that needs to be - * retransmitted - */ - transaction->actual_bytes += bytes_this_transfer; - if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS) - buffer_space_left = transaction->iso_packets[0].length - - transaction->actual_bytes; - else - buffer_space_left = transaction->buffer_length - - transaction->actual_bytes; - - /* - * We need to remember the PID toggle state for the next transaction. - * The hardware already updated it for the next transaction - */ - pipe->pid_toggle = !(usbc_hctsiz.s.pid == 0); - - /* - * For high speed bulk out, assume the next transaction will need to do - * a ping before proceeding. If this isn't true the ACK processing below - * will clear this flag - */ - if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) && - (pipe->transfer_type == CVMX_USB_TRANSFER_BULK) && - (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT)) - pipe->flags |= CVMX_USB_PIPE_FLAGS_NEED_PING; - - if (WARN_ON_ONCE(bytes_this_transfer < 0)) { - /* - * In some rare cases the DMA engine seems to get stuck and - * keeps substracting same byte count over and over again. In - * such case we just need to fail every transaction. - */ - cvmx_usb_complete(usb, pipe, transaction, - CVMX_USB_STATUS_ERROR); - return 0; - } - - if (usbc_hcint.s.stall) { - /* - * STALL as a response means this transaction cannot be - * completed because the device can't process transactions. Tell - * the user. Any data that was transferred will be counted on - * the actual bytes transferred - */ - pipe->pid_toggle = 0; - cvmx_usb_complete(usb, pipe, transaction, - CVMX_USB_STATUS_STALL); - } else if (usbc_hcint.s.xacterr) { - /* - * XactErr as a response means the device signaled - * something wrong with the transfer. For example, PID - * toggle errors cause these. - */ - cvmx_usb_complete(usb, pipe, transaction, - CVMX_USB_STATUS_XACTERR); - } else if (usbc_hcint.s.bblerr) { - /* Babble Error (BblErr) */ - cvmx_usb_complete(usb, pipe, transaction, - CVMX_USB_STATUS_BABBLEERR); - } else if (usbc_hcint.s.datatglerr) { - /* Data toggle error */ - cvmx_usb_complete(usb, pipe, transaction, - CVMX_USB_STATUS_DATATGLERR); - } else if (usbc_hcint.s.nyet) { - /* - * NYET as a response is only allowed in three cases: as a - * response to a ping, as a response to a split transaction, and - * as a response to a bulk out. The ping case is handled by - * hardware, so we only have splits and bulk out - */ - if (!cvmx_usb_pipe_needs_split(usb, pipe)) { - transaction->retries = 0; - /* - * If there is more data to go then we need to try - * again. Otherwise this transaction is complete - */ - if ((buffer_space_left == 0) || - (bytes_in_last_packet < pipe->max_packet)) - cvmx_usb_complete(usb, pipe, - transaction, - CVMX_USB_STATUS_OK); - } else { - /* - * Split transactions retry the split complete 4 times - * then rewind to the start split and do the entire - * transactions again - */ - transaction->retries++; - if ((transaction->retries & 0x3) == 0) { - /* - * Rewind to the beginning of the transaction by - * anding off the split complete bit - */ - transaction->stage &= ~1; - pipe->split_sc_frame = -1; - } - } - } else if (usbc_hcint.s.ack) { - transaction->retries = 0; - /* - * The ACK bit can only be checked after the other error bits. - * This is because a multi packet transfer may succeed in a - * number of packets and then get a different response on the - * last packet. In this case both ACK and the last response bit - * will be set. If none of the other response bits is set, then - * the last packet must have been an ACK - * - * Since we got an ACK, we know we don't need to do a ping on - * this pipe - */ - pipe->flags &= ~CVMX_USB_PIPE_FLAGS_NEED_PING; - - switch (transaction->type) { - case CVMX_USB_TRANSFER_CONTROL: - cvmx_usb_transfer_control(usb, pipe, transaction, - usbc_hcchar, - buffer_space_left, - bytes_in_last_packet); - break; - case CVMX_USB_TRANSFER_BULK: - cvmx_usb_transfer_bulk(usb, pipe, transaction, - usbc_hcint, buffer_space_left, - bytes_in_last_packet); - break; - case CVMX_USB_TRANSFER_INTERRUPT: - cvmx_usb_transfer_intr(usb, pipe, transaction, - buffer_space_left, - bytes_in_last_packet); - break; - case CVMX_USB_TRANSFER_ISOCHRONOUS: - cvmx_usb_transfer_isoc(usb, pipe, transaction, - buffer_space_left, - bytes_in_last_packet, - bytes_this_transfer); - break; - } - } else if (usbc_hcint.s.nak) { - /* - * If this was a split then clear our split in progress marker. - */ - if (usb->active_split == transaction) - usb->active_split = NULL; - /* - * NAK as a response means the device couldn't accept the - * transaction, but it should be retried in the future. Rewind - * to the beginning of the transaction by anding off the split - * complete bit. Retry in the next interval - */ - transaction->retries = 0; - transaction->stage &= ~1; - pipe->next_tx_frame += pipe->interval; - if (pipe->next_tx_frame < usb->frame_number) - pipe->next_tx_frame = usb->frame_number + - pipe->interval - - (usb->frame_number - pipe->next_tx_frame) % - pipe->interval; - } else { - struct cvmx_usb_port_status port; - - port = cvmx_usb_get_status(usb); - if (port.port_enabled) { - /* We'll retry the exact same transaction again */ - transaction->retries++; - } else { - /* - * We get channel halted interrupts with no result bits - * sets when the cable is unplugged - */ - cvmx_usb_complete(usb, pipe, transaction, - CVMX_USB_STATUS_ERROR); - } - } - return 0; -} - -static void octeon_usb_port_callback(struct octeon_hcd *usb) -{ - spin_unlock(&usb->lock); - usb_hcd_poll_rh_status(octeon_to_hcd(usb)); - spin_lock(&usb->lock); -} - -/** - * Poll the USB block for status and call all needed callback - * handlers. This function is meant to be called in the interrupt - * handler for the USB controller. It can also be called - * periodically in a loop for non-interrupt based operation. - * - * @usb: USB device state populated by cvmx_usb_initialize(). - * - * Returns: 0 or a negative error code. - */ -static int cvmx_usb_poll(struct octeon_hcd *usb) -{ - union cvmx_usbcx_hfnum usbc_hfnum; - union cvmx_usbcx_gintsts usbc_gintsts; - - prefetch_range(usb, sizeof(*usb)); - - /* Update the frame counter */ - usbc_hfnum.u32 = cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index)); - if ((usb->frame_number & 0x3fff) > usbc_hfnum.s.frnum) - usb->frame_number += 0x4000; - usb->frame_number &= ~0x3fffull; - usb->frame_number |= usbc_hfnum.s.frnum; - - /* Read the pending interrupts */ - usbc_gintsts.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_GINTSTS(usb->index)); - - /* Clear the interrupts now that we know about them */ - cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index), - usbc_gintsts.u32); - - if (usbc_gintsts.s.rxflvl) { - /* - * RxFIFO Non-Empty (RxFLvl) - * Indicates that there is at least one packet pending to be - * read from the RxFIFO. - * - * In DMA mode this is handled by hardware - */ - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) - cvmx_usb_poll_rx_fifo(usb); - } - if (usbc_gintsts.s.ptxfemp || usbc_gintsts.s.nptxfemp) { - /* Fill the Tx FIFOs when not in DMA mode */ - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) - cvmx_usb_poll_tx_fifo(usb); - } - if (usbc_gintsts.s.disconnint || usbc_gintsts.s.prtint) { - union cvmx_usbcx_hprt usbc_hprt; - /* - * Disconnect Detected Interrupt (DisconnInt) - * Asserted when a device disconnect is detected. - * - * Host Port Interrupt (PrtInt) - * The core sets this bit to indicate a change in port status of - * one of the O2P USB core ports in Host mode. The application - * must read the Host Port Control and Status (HPRT) register to - * determine the exact event that caused this interrupt. The - * application must clear the appropriate status bit in the Host - * Port Control and Status register to clear this bit. - * - * Call the user's port callback - */ - octeon_usb_port_callback(usb); - /* Clear the port change bits */ - usbc_hprt.u32 = - cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); - usbc_hprt.s.prtena = 0; - cvmx_usb_write_csr32(usb, CVMX_USBCX_HPRT(usb->index), - usbc_hprt.u32); - } - if (usbc_gintsts.s.hchint) { - /* - * Host Channels Interrupt (HChInt) - * The core sets this bit to indicate that an interrupt is - * pending on one of the channels of the core (in Host mode). - * The application must read the Host All Channels Interrupt - * (HAINT) register to determine the exact number of the channel - * on which the interrupt occurred, and then read the - * corresponding Host Channel-n Interrupt (HCINTn) register to - * determine the exact cause of the interrupt. The application - * must clear the appropriate status bit in the HCINTn register - * to clear this bit. - */ - union cvmx_usbcx_haint usbc_haint; - - usbc_haint.u32 = cvmx_usb_read_csr32(usb, - CVMX_USBCX_HAINT(usb->index)); - while (usbc_haint.u32) { - int channel; - - channel = __fls(usbc_haint.u32); - cvmx_usb_poll_channel(usb, channel); - usbc_haint.u32 ^= 1 << channel; - } - } - - cvmx_usb_schedule(usb, usbc_gintsts.s.sof); - - return 0; -} - -/* convert between an HCD pointer and the corresponding struct octeon_hcd */ -static inline struct octeon_hcd *hcd_to_octeon(struct usb_hcd *hcd) -{ - return (struct octeon_hcd *)(hcd->hcd_priv); -} - -static irqreturn_t octeon_usb_irq(struct usb_hcd *hcd) -{ - struct octeon_hcd *usb = hcd_to_octeon(hcd); - unsigned long flags; - - spin_lock_irqsave(&usb->lock, flags); - cvmx_usb_poll(usb); - spin_unlock_irqrestore(&usb->lock, flags); - return IRQ_HANDLED; -} - -static int octeon_usb_start(struct usb_hcd *hcd) -{ - hcd->state = HC_STATE_RUNNING; - return 0; -} - -static void octeon_usb_stop(struct usb_hcd *hcd) -{ - hcd->state = HC_STATE_HALT; -} - -static int octeon_usb_get_frame_number(struct usb_hcd *hcd) -{ - struct octeon_hcd *usb = hcd_to_octeon(hcd); - - return cvmx_usb_get_frame_number(usb); -} - -static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, - struct urb *urb, - gfp_t mem_flags) -{ - struct octeon_hcd *usb = hcd_to_octeon(hcd); - struct device *dev = hcd->self.controller; - struct cvmx_usb_transaction *transaction = NULL; - struct cvmx_usb_pipe *pipe; - unsigned long flags; - struct cvmx_usb_iso_packet *iso_packet; - struct usb_host_endpoint *ep = urb->ep; - int rc; - - urb->status = 0; - spin_lock_irqsave(&usb->lock, flags); - - rc = usb_hcd_link_urb_to_ep(hcd, urb); - if (rc) { - spin_unlock_irqrestore(&usb->lock, flags); - return rc; - } - - if (!ep->hcpriv) { - enum cvmx_usb_transfer transfer_type; - enum cvmx_usb_speed speed; - int split_device = 0; - int split_port = 0; - - switch (usb_pipetype(urb->pipe)) { - case PIPE_ISOCHRONOUS: - transfer_type = CVMX_USB_TRANSFER_ISOCHRONOUS; - break; - case PIPE_INTERRUPT: - transfer_type = CVMX_USB_TRANSFER_INTERRUPT; - break; - case PIPE_CONTROL: - transfer_type = CVMX_USB_TRANSFER_CONTROL; - break; - default: - transfer_type = CVMX_USB_TRANSFER_BULK; - break; - } - switch (urb->dev->speed) { - case USB_SPEED_LOW: - speed = CVMX_USB_SPEED_LOW; - break; - case USB_SPEED_FULL: - speed = CVMX_USB_SPEED_FULL; - break; - default: - speed = CVMX_USB_SPEED_HIGH; - break; - } - /* - * For slow devices on high speed ports we need to find the hub - * that does the speed translation so we know where to send the - * split transactions. - */ - if (speed != CVMX_USB_SPEED_HIGH) { - /* - * Start at this device and work our way up the usb - * tree. - */ - struct usb_device *dev = urb->dev; - - while (dev->parent) { - /* - * If our parent is high speed then he'll - * receive the splits. - */ - if (dev->parent->speed == USB_SPEED_HIGH) { - split_device = dev->parent->devnum; - split_port = dev->portnum; - break; - } - /* - * Move up the tree one level. If we make it all - * the way up the tree, then the port must not - * be in high speed mode and we don't need a - * split. - */ - dev = dev->parent; - } - } - pipe = cvmx_usb_open_pipe(usb, usb_pipedevice(urb->pipe), - usb_pipeendpoint(urb->pipe), speed, - le16_to_cpu(ep->desc.wMaxPacketSize) - & 0x7ff, - transfer_type, - usb_pipein(urb->pipe) ? - CVMX_USB_DIRECTION_IN : - CVMX_USB_DIRECTION_OUT, - urb->interval, - (le16_to_cpu(ep->desc.wMaxPacketSize) - >> 11) & 0x3, - split_device, split_port); - if (!pipe) { - usb_hcd_unlink_urb_from_ep(hcd, urb); - spin_unlock_irqrestore(&usb->lock, flags); - dev_dbg(dev, "Failed to create pipe\n"); - return -ENOMEM; - } - ep->hcpriv = pipe; - } else { - pipe = ep->hcpriv; - } - - switch (usb_pipetype(urb->pipe)) { - case PIPE_ISOCHRONOUS: - dev_dbg(dev, "Submit isochronous to %d.%d\n", - usb_pipedevice(urb->pipe), - usb_pipeendpoint(urb->pipe)); - /* - * Allocate a structure to use for our private list of - * isochronous packets. - */ - iso_packet = kmalloc_array(urb->number_of_packets, - sizeof(struct cvmx_usb_iso_packet), - GFP_ATOMIC); - if (iso_packet) { - int i; - /* Fill the list with the data from the URB */ - for (i = 0; i < urb->number_of_packets; i++) { - iso_packet[i].offset = - urb->iso_frame_desc[i].offset; - iso_packet[i].length = - urb->iso_frame_desc[i].length; - iso_packet[i].status = CVMX_USB_STATUS_ERROR; - } - /* - * Store a pointer to the list in the URB setup_packet - * field. We know this currently isn't being used and - * this saves us a bunch of logic. - */ - urb->setup_packet = (char *)iso_packet; - transaction = cvmx_usb_submit_isochronous(usb, - pipe, urb); - /* - * If submit failed we need to free our private packet - * list. - */ - if (!transaction) { - urb->setup_packet = NULL; - kfree(iso_packet); - } - } - break; - case PIPE_INTERRUPT: - dev_dbg(dev, "Submit interrupt to %d.%d\n", - usb_pipedevice(urb->pipe), - usb_pipeendpoint(urb->pipe)); - transaction = cvmx_usb_submit_interrupt(usb, pipe, urb); - break; - case PIPE_CONTROL: - dev_dbg(dev, "Submit control to %d.%d\n", - usb_pipedevice(urb->pipe), - usb_pipeendpoint(urb->pipe)); - transaction = cvmx_usb_submit_control(usb, pipe, urb); - break; - case PIPE_BULK: - dev_dbg(dev, "Submit bulk to %d.%d\n", - usb_pipedevice(urb->pipe), - usb_pipeendpoint(urb->pipe)); - transaction = cvmx_usb_submit_bulk(usb, pipe, urb); - break; - } - if (!transaction) { - usb_hcd_unlink_urb_from_ep(hcd, urb); - spin_unlock_irqrestore(&usb->lock, flags); - dev_dbg(dev, "Failed to submit\n"); - return -ENOMEM; - } - urb->hcpriv = transaction; - spin_unlock_irqrestore(&usb->lock, flags); - return 0; -} - -static int octeon_usb_urb_dequeue(struct usb_hcd *hcd, - struct urb *urb, - int status) -{ - struct octeon_hcd *usb = hcd_to_octeon(hcd); - unsigned long flags; - int rc; - - if (!urb->dev) - return -EINVAL; - - spin_lock_irqsave(&usb->lock, flags); - - rc = usb_hcd_check_unlink_urb(hcd, urb, status); - if (rc) - goto out; - - urb->status = status; - cvmx_usb_cancel(usb, urb->ep->hcpriv, urb->hcpriv); - -out: - spin_unlock_irqrestore(&usb->lock, flags); - - return rc; -} - -static void octeon_usb_endpoint_disable(struct usb_hcd *hcd, - struct usb_host_endpoint *ep) -{ - struct device *dev = hcd->self.controller; - - if (ep->hcpriv) { - struct octeon_hcd *usb = hcd_to_octeon(hcd); - struct cvmx_usb_pipe *pipe = ep->hcpriv; - unsigned long flags; - - spin_lock_irqsave(&usb->lock, flags); - cvmx_usb_cancel_all(usb, pipe); - if (cvmx_usb_close_pipe(usb, pipe)) - dev_dbg(dev, "Closing pipe %p failed\n", pipe); - spin_unlock_irqrestore(&usb->lock, flags); - ep->hcpriv = NULL; - } -} - -static int octeon_usb_hub_status_data(struct usb_hcd *hcd, char *buf) -{ - struct octeon_hcd *usb = hcd_to_octeon(hcd); - struct cvmx_usb_port_status port_status; - unsigned long flags; - - spin_lock_irqsave(&usb->lock, flags); - port_status = cvmx_usb_get_status(usb); - spin_unlock_irqrestore(&usb->lock, flags); - buf[0] = port_status.connect_change << 1; - - return buf[0] != 0; -} - -static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, - u16 wIndex, char *buf, u16 wLength) -{ - struct octeon_hcd *usb = hcd_to_octeon(hcd); - struct device *dev = hcd->self.controller; - struct cvmx_usb_port_status usb_port_status; - int port_status; - struct usb_hub_descriptor *desc; - unsigned long flags; - - switch (typeReq) { - case ClearHubFeature: - dev_dbg(dev, "ClearHubFeature\n"); - switch (wValue) { - case C_HUB_LOCAL_POWER: - case C_HUB_OVER_CURRENT: - /* Nothing required here */ - break; - default: - return -EINVAL; - } - break; - case ClearPortFeature: - dev_dbg(dev, "ClearPortFeature\n"); - if (wIndex != 1) { - dev_dbg(dev, " INVALID\n"); - return -EINVAL; - } - - switch (wValue) { - case USB_PORT_FEAT_ENABLE: - dev_dbg(dev, " ENABLE\n"); - spin_lock_irqsave(&usb->lock, flags); - cvmx_usb_disable(usb); - spin_unlock_irqrestore(&usb->lock, flags); - break; - case USB_PORT_FEAT_SUSPEND: - dev_dbg(dev, " SUSPEND\n"); - /* Not supported on Octeon */ - break; - case USB_PORT_FEAT_POWER: - dev_dbg(dev, " POWER\n"); - /* Not supported on Octeon */ - break; - case USB_PORT_FEAT_INDICATOR: - dev_dbg(dev, " INDICATOR\n"); - /* Port inidicator not supported */ - break; - case USB_PORT_FEAT_C_CONNECTION: - dev_dbg(dev, " C_CONNECTION\n"); - /* Clears drivers internal connect status change flag */ - spin_lock_irqsave(&usb->lock, flags); - usb->port_status = cvmx_usb_get_status(usb); - spin_unlock_irqrestore(&usb->lock, flags); - break; - case USB_PORT_FEAT_C_RESET: - dev_dbg(dev, " C_RESET\n"); - /* - * Clears the driver's internal Port Reset Change flag. - */ - spin_lock_irqsave(&usb->lock, flags); - usb->port_status = cvmx_usb_get_status(usb); - spin_unlock_irqrestore(&usb->lock, flags); - break; - case USB_PORT_FEAT_C_ENABLE: - dev_dbg(dev, " C_ENABLE\n"); - /* - * Clears the driver's internal Port Enable/Disable - * Change flag. - */ - spin_lock_irqsave(&usb->lock, flags); - usb->port_status = cvmx_usb_get_status(usb); - spin_unlock_irqrestore(&usb->lock, flags); - break; - case USB_PORT_FEAT_C_SUSPEND: - dev_dbg(dev, " C_SUSPEND\n"); - /* - * Clears the driver's internal Port Suspend Change - * flag, which is set when resume signaling on the host - * port is complete. - */ - break; - case USB_PORT_FEAT_C_OVER_CURRENT: - dev_dbg(dev, " C_OVER_CURRENT\n"); - /* Clears the driver's overcurrent Change flag */ - spin_lock_irqsave(&usb->lock, flags); - usb->port_status = cvmx_usb_get_status(usb); - spin_unlock_irqrestore(&usb->lock, flags); - break; - default: - dev_dbg(dev, " UNKNOWN\n"); - return -EINVAL; - } - break; - case GetHubDescriptor: - dev_dbg(dev, "GetHubDescriptor\n"); - desc = (struct usb_hub_descriptor *)buf; - desc->bDescLength = 9; - desc->bDescriptorType = 0x29; - desc->bNbrPorts = 1; - desc->wHubCharacteristics = cpu_to_le16(0x08); - desc->bPwrOn2PwrGood = 1; - desc->bHubContrCurrent = 0; - desc->u.hs.DeviceRemovable[0] = 0; - desc->u.hs.DeviceRemovable[1] = 0xff; - break; - case GetHubStatus: - dev_dbg(dev, "GetHubStatus\n"); - *(__le32 *)buf = 0; - break; - case GetPortStatus: - dev_dbg(dev, "GetPortStatus\n"); - if (wIndex != 1) { - dev_dbg(dev, " INVALID\n"); - return -EINVAL; - } - - spin_lock_irqsave(&usb->lock, flags); - usb_port_status = cvmx_usb_get_status(usb); - spin_unlock_irqrestore(&usb->lock, flags); - port_status = 0; - - if (usb_port_status.connect_change) { - port_status |= (1 << USB_PORT_FEAT_C_CONNECTION); - dev_dbg(dev, " C_CONNECTION\n"); - } - - if (usb_port_status.port_enabled) { - port_status |= (1 << USB_PORT_FEAT_C_ENABLE); - dev_dbg(dev, " C_ENABLE\n"); - } - - if (usb_port_status.connected) { - port_status |= (1 << USB_PORT_FEAT_CONNECTION); - dev_dbg(dev, " CONNECTION\n"); - } - - if (usb_port_status.port_enabled) { - port_status |= (1 << USB_PORT_FEAT_ENABLE); - dev_dbg(dev, " ENABLE\n"); - } - - if (usb_port_status.port_over_current) { - port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT); - dev_dbg(dev, " OVER_CURRENT\n"); - } - - if (usb_port_status.port_powered) { - port_status |= (1 << USB_PORT_FEAT_POWER); - dev_dbg(dev, " POWER\n"); - } - - if (usb_port_status.port_speed == CVMX_USB_SPEED_HIGH) { - port_status |= USB_PORT_STAT_HIGH_SPEED; - dev_dbg(dev, " HIGHSPEED\n"); - } else if (usb_port_status.port_speed == CVMX_USB_SPEED_LOW) { - port_status |= (1 << USB_PORT_FEAT_LOWSPEED); - dev_dbg(dev, " LOWSPEED\n"); - } - - *((__le32 *)buf) = cpu_to_le32(port_status); - break; - case SetHubFeature: - dev_dbg(dev, "SetHubFeature\n"); - /* No HUB features supported */ - break; - case SetPortFeature: - dev_dbg(dev, "SetPortFeature\n"); - if (wIndex != 1) { - dev_dbg(dev, " INVALID\n"); - return -EINVAL; - } - - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - dev_dbg(dev, " SUSPEND\n"); - return -EINVAL; - case USB_PORT_FEAT_POWER: - dev_dbg(dev, " POWER\n"); - /* - * Program the port power bit to drive VBUS on the USB. - */ - spin_lock_irqsave(&usb->lock, flags); - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), - cvmx_usbcx_hprt, prtpwr, 1); - spin_unlock_irqrestore(&usb->lock, flags); - return 0; - case USB_PORT_FEAT_RESET: - dev_dbg(dev, " RESET\n"); - spin_lock_irqsave(&usb->lock, flags); - cvmx_usb_reset_port(usb); - spin_unlock_irqrestore(&usb->lock, flags); - return 0; - case USB_PORT_FEAT_INDICATOR: - dev_dbg(dev, " INDICATOR\n"); - /* Not supported */ - break; - default: - dev_dbg(dev, " UNKNOWN\n"); - return -EINVAL; - } - break; - default: - dev_dbg(dev, "Unknown root hub request\n"); - return -EINVAL; - } - return 0; -} - -static const struct hc_driver octeon_hc_driver = { - .description = "Octeon USB", - .product_desc = "Octeon Host Controller", - .hcd_priv_size = sizeof(struct octeon_hcd), - .irq = octeon_usb_irq, - .flags = HCD_MEMORY | HCD_DMA | HCD_USB2, - .start = octeon_usb_start, - .stop = octeon_usb_stop, - .urb_enqueue = octeon_usb_urb_enqueue, - .urb_dequeue = octeon_usb_urb_dequeue, - .endpoint_disable = octeon_usb_endpoint_disable, - .get_frame_number = octeon_usb_get_frame_number, - .hub_status_data = octeon_usb_hub_status_data, - .hub_control = octeon_usb_hub_control, - .map_urb_for_dma = octeon_map_urb_for_dma, - .unmap_urb_for_dma = octeon_unmap_urb_for_dma, -}; - -static int octeon_usb_probe(struct platform_device *pdev) -{ - int status; - int initialize_flags; - int usb_num; - struct resource *res_mem; - struct device_node *usbn_node; - int irq = platform_get_irq(pdev, 0); - struct device *dev = &pdev->dev; - struct octeon_hcd *usb; - struct usb_hcd *hcd; - u32 clock_rate = 48000000; - bool is_crystal_clock = false; - const char *clock_type; - int i; - - if (!dev->of_node) { - dev_err(dev, "Error: empty of_node\n"); - return -ENXIO; - } - usbn_node = dev->of_node->parent; - - i = of_property_read_u32(usbn_node, - "clock-frequency", &clock_rate); - if (i) - i = of_property_read_u32(usbn_node, - "refclk-frequency", &clock_rate); - if (i) { - dev_err(dev, "No USBN \"clock-frequency\"\n"); - return -ENXIO; - } - switch (clock_rate) { - case 12000000: - initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ; - break; - case 24000000: - initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ; - break; - case 48000000: - initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ; - break; - default: - dev_err(dev, "Illegal USBN \"clock-frequency\" %u\n", - clock_rate); - return -ENXIO; - } - - i = of_property_read_string(usbn_node, - "cavium,refclk-type", &clock_type); - if (i) - i = of_property_read_string(usbn_node, - "refclk-type", &clock_type); - - if (!i && strcmp("crystal", clock_type) == 0) - is_crystal_clock = true; - - if (is_crystal_clock) - initialize_flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI; - else - initialize_flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND; - - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res_mem) { - dev_err(dev, "found no memory resource\n"); - return -ENXIO; - } - usb_num = (res_mem->start >> 44) & 1; - - if (irq < 0) { - /* Defective device tree, but we know how to fix it. */ - irq_hw_number_t hwirq = usb_num ? (1 << 6) + 17 : 56; - - irq = irq_create_mapping(NULL, hwirq); - } - - /* - * Set the DMA mask to 64bits so we get buffers already translated for - * DMA. - */ - i = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64)); - if (i) - return i; - - /* - * Only cn52XX and cn56XX have DWC_OTG USB hardware and the - * IOB priority registers. Under heavy network load USB - * hardware can be starved by the IOB causing a crash. Give - * it a priority boost if it has been waiting more than 400 - * cycles to avoid this situation. - * - * Testing indicates that a cnt_val of 8192 is not sufficient, - * but no failures are seen with 4096. We choose a value of - * 400 to give a safety factor of 10. - */ - if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) { - union cvmx_iob_n2c_l2c_pri_cnt pri_cnt; - - pri_cnt.u64 = 0; - pri_cnt.s.cnt_enb = 1; - pri_cnt.s.cnt_val = 400; - cvmx_write_csr(CVMX_IOB_N2C_L2C_PRI_CNT, pri_cnt.u64); - } - - hcd = usb_create_hcd(&octeon_hc_driver, dev, dev_name(dev)); - if (!hcd) { - dev_dbg(dev, "Failed to allocate memory for HCD\n"); - return -1; - } - hcd->uses_new_polling = 1; - usb = (struct octeon_hcd *)hcd->hcd_priv; - - spin_lock_init(&usb->lock); - - usb->init_flags = initialize_flags; - - /* Initialize the USB state structure */ - usb->index = usb_num; - INIT_LIST_HEAD(&usb->idle_pipes); - for (i = 0; i < ARRAY_SIZE(usb->active_pipes); i++) - INIT_LIST_HEAD(&usb->active_pipes[i]); - - /* Due to an errata, CN31XX doesn't support DMA */ - if (OCTEON_IS_MODEL(OCTEON_CN31XX)) { - usb->init_flags |= CVMX_USB_INITIALIZE_FLAGS_NO_DMA; - /* Only use one channel with non DMA */ - usb->idle_hardware_channels = 0x1; - } else if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) { - /* CN5XXX have an errata with channel 3 */ - usb->idle_hardware_channels = 0xf7; - } else { - usb->idle_hardware_channels = 0xff; - } - - status = cvmx_usb_initialize(dev, usb); - if (status) { - dev_dbg(dev, "USB initialization failed with %d\n", status); - usb_put_hcd(hcd); - return -1; - } - - status = usb_add_hcd(hcd, irq, 0); - if (status) { - dev_dbg(dev, "USB add HCD failed with %d\n", status); - usb_put_hcd(hcd); - return -1; - } - device_wakeup_enable(hcd->self.controller); - - dev_info(dev, "Registered HCD for port %d on irq %d\n", usb_num, irq); - - return 0; -} - -static int octeon_usb_remove(struct platform_device *pdev) -{ - int status; - struct device *dev = &pdev->dev; - struct usb_hcd *hcd = dev_get_drvdata(dev); - struct octeon_hcd *usb = hcd_to_octeon(hcd); - unsigned long flags; - - usb_remove_hcd(hcd); - spin_lock_irqsave(&usb->lock, flags); - status = cvmx_usb_shutdown(usb); - spin_unlock_irqrestore(&usb->lock, flags); - if (status) - dev_dbg(dev, "USB shutdown failed with %d\n", status); - - usb_put_hcd(hcd); - - return 0; -} - -static const struct of_device_id octeon_usb_match[] = { - { - .compatible = "cavium,octeon-5750-usbc", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, octeon_usb_match); - -static struct platform_driver octeon_usb_driver = { - .driver = { - .name = "octeon-hcd", - .of_match_table = octeon_usb_match, - }, - .probe = octeon_usb_probe, - .remove = octeon_usb_remove, -}; - -static int __init octeon_usb_driver_init(void) -{ - if (usb_disabled()) - return 0; - - return platform_driver_register(&octeon_usb_driver); -} -module_init(octeon_usb_driver_init); - -static void __exit octeon_usb_driver_exit(void) -{ - if (usb_disabled()) - return; - - platform_driver_unregister(&octeon_usb_driver); -} -module_exit(octeon_usb_driver_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Cavium, Inc. "); -MODULE_DESCRIPTION("Cavium Inc. OCTEON USB Host driver."); diff --git a/drivers/staging/octeon-usb/octeon-hcd.h b/drivers/staging/octeon-usb/octeon-hcd.h deleted file mode 100644 index 9ed619c93a4e..000000000000 --- a/drivers/staging/octeon-usb/octeon-hcd.h +++ /dev/null @@ -1,1847 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Octeon HCD hardware register definitions. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Some parts of the code were originally released under BSD license: - * - * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * * Neither the name of Cavium Networks nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * This Software, including technical data, may be subject to U.S. export - * control laws, including the U.S. Export Administration Act and its associated - * regulations, and may be subject to export or import regulations in other - * countries. - * - * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" - * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR - * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO - * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION - * OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM - * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, - * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF - * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR - * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR - * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. - */ - -#ifndef __OCTEON_HCD_H__ -#define __OCTEON_HCD_H__ - -#include - -#define CVMX_USBCXBASE 0x00016F0010000000ull -#define CVMX_USBCXREG1(reg, bid) \ - (CVMX_ADD_IO_SEG(CVMX_USBCXBASE | reg) + \ - ((bid) & 1) * 0x100000000000ull) -#define CVMX_USBCXREG2(reg, bid, off) \ - (CVMX_ADD_IO_SEG(CVMX_USBCXBASE | reg) + \ - (((off) & 7) + ((bid) & 1) * 0x8000000000ull) * 32) - -#define CVMX_USBCX_GAHBCFG(bid) CVMX_USBCXREG1(0x008, bid) -#define CVMX_USBCX_GHWCFG3(bid) CVMX_USBCXREG1(0x04c, bid) -#define CVMX_USBCX_GINTMSK(bid) CVMX_USBCXREG1(0x018, bid) -#define CVMX_USBCX_GINTSTS(bid) CVMX_USBCXREG1(0x014, bid) -#define CVMX_USBCX_GNPTXFSIZ(bid) CVMX_USBCXREG1(0x028, bid) -#define CVMX_USBCX_GNPTXSTS(bid) CVMX_USBCXREG1(0x02c, bid) -#define CVMX_USBCX_GOTGCTL(bid) CVMX_USBCXREG1(0x000, bid) -#define CVMX_USBCX_GRSTCTL(bid) CVMX_USBCXREG1(0x010, bid) -#define CVMX_USBCX_GRXFSIZ(bid) CVMX_USBCXREG1(0x024, bid) -#define CVMX_USBCX_GRXSTSPH(bid) CVMX_USBCXREG1(0x020, bid) -#define CVMX_USBCX_GUSBCFG(bid) CVMX_USBCXREG1(0x00c, bid) -#define CVMX_USBCX_HAINT(bid) CVMX_USBCXREG1(0x414, bid) -#define CVMX_USBCX_HAINTMSK(bid) CVMX_USBCXREG1(0x418, bid) -#define CVMX_USBCX_HCCHARX(off, bid) CVMX_USBCXREG2(0x500, bid, off) -#define CVMX_USBCX_HCFG(bid) CVMX_USBCXREG1(0x400, bid) -#define CVMX_USBCX_HCINTMSKX(off, bid) CVMX_USBCXREG2(0x50c, bid, off) -#define CVMX_USBCX_HCINTX(off, bid) CVMX_USBCXREG2(0x508, bid, off) -#define CVMX_USBCX_HCSPLTX(off, bid) CVMX_USBCXREG2(0x504, bid, off) -#define CVMX_USBCX_HCTSIZX(off, bid) CVMX_USBCXREG2(0x510, bid, off) -#define CVMX_USBCX_HFIR(bid) CVMX_USBCXREG1(0x404, bid) -#define CVMX_USBCX_HFNUM(bid) CVMX_USBCXREG1(0x408, bid) -#define CVMX_USBCX_HPRT(bid) CVMX_USBCXREG1(0x440, bid) -#define CVMX_USBCX_HPTXFSIZ(bid) CVMX_USBCXREG1(0x100, bid) -#define CVMX_USBCX_HPTXSTS(bid) CVMX_USBCXREG1(0x410, bid) - -#define CVMX_USBNXBID1(bid) (((bid) & 1) * 0x10000000ull) -#define CVMX_USBNXBID2(bid) (((bid) & 1) * 0x100000000000ull) - -#define CVMX_USBNXREG1(reg, bid) \ - (CVMX_ADD_IO_SEG(0x0001180068000000ull | reg) + CVMX_USBNXBID1(bid)) -#define CVMX_USBNXREG2(reg, bid) \ - (CVMX_ADD_IO_SEG(0x00016F0000000000ull | reg) + CVMX_USBNXBID2(bid)) - -#define CVMX_USBNX_CLK_CTL(bid) CVMX_USBNXREG1(0x10, bid) -#define CVMX_USBNX_DMA0_INB_CHN0(bid) CVMX_USBNXREG2(0x818, bid) -#define CVMX_USBNX_DMA0_OUTB_CHN0(bid) CVMX_USBNXREG2(0x858, bid) -#define CVMX_USBNX_USBP_CTL_STATUS(bid) CVMX_USBNXREG1(0x18, bid) - -/** - * cvmx_usbc#_gahbcfg - * - * Core AHB Configuration Register (GAHBCFG) - * - * This register can be used to configure the core after power-on or a change in - * mode of operation. This register mainly contains AHB system-related - * configuration parameters. The AHB is the processor interface to the O2P USB - * core. In general, software need not know about this interface except to - * program the values as specified. - * - * The application must program this register as part of the O2P USB core - * initialization. Do not change this register after the initial programming. - */ -union cvmx_usbcx_gahbcfg { - u32 u32; - /** - * struct cvmx_usbcx_gahbcfg_s - * @ptxfemplvl: Periodic TxFIFO Empty Level (PTxFEmpLvl) - * Software should set this bit to 0x1. - * Indicates when the Periodic TxFIFO Empty Interrupt bit in the - * Core Interrupt register (GINTSTS.PTxFEmp) is triggered. This - * bit is used only in Slave mode. - * * 1'b0: GINTSTS.PTxFEmp interrupt indicates that the Periodic - * TxFIFO is half empty - * * 1'b1: GINTSTS.PTxFEmp interrupt indicates that the Periodic - * TxFIFO is completely empty - * @nptxfemplvl: Non-Periodic TxFIFO Empty Level (NPTxFEmpLvl) - * Software should set this bit to 0x1. - * Indicates when the Non-Periodic TxFIFO Empty Interrupt bit in - * the Core Interrupt register (GINTSTS.NPTxFEmp) is triggered. - * This bit is used only in Slave mode. - * * 1'b0: GINTSTS.NPTxFEmp interrupt indicates that the Non- - * Periodic TxFIFO is half empty - * * 1'b1: GINTSTS.NPTxFEmp interrupt indicates that the Non- - * Periodic TxFIFO is completely empty - * @dmaen: DMA Enable (DMAEn) - * * 1'b0: Core operates in Slave mode - * * 1'b1: Core operates in a DMA mode - * @hbstlen: Burst Length/Type (HBstLen) - * This field has not effect and should be left as 0x0. - * @glblintrmsk: Global Interrupt Mask (GlblIntrMsk) - * Software should set this field to 0x1. - * The application uses this bit to mask or unmask the interrupt - * line assertion to itself. Irrespective of this bit's setting, - * the interrupt status registers are updated by the core. - * * 1'b0: Mask the interrupt assertion to the application. - * * 1'b1: Unmask the interrupt assertion to the application. - */ - struct cvmx_usbcx_gahbcfg_s { - __BITFIELD_FIELD(u32 reserved_9_31 : 23, - __BITFIELD_FIELD(u32 ptxfemplvl : 1, - __BITFIELD_FIELD(u32 nptxfemplvl : 1, - __BITFIELD_FIELD(u32 reserved_6_6 : 1, - __BITFIELD_FIELD(u32 dmaen : 1, - __BITFIELD_FIELD(u32 hbstlen : 4, - __BITFIELD_FIELD(u32 glblintrmsk : 1, - ;))))))) - } s; -}; - -/** - * cvmx_usbc#_ghwcfg3 - * - * User HW Config3 Register (GHWCFG3) - * - * This register contains the configuration options of the O2P USB core. - */ -union cvmx_usbcx_ghwcfg3 { - u32 u32; - /** - * struct cvmx_usbcx_ghwcfg3_s - * @dfifodepth: DFIFO Depth (DfifoDepth) - * This value is in terms of 32-bit words. - * * Minimum value is 32 - * * Maximum value is 32768 - * @ahbphysync: AHB and PHY Synchronous (AhbPhySync) - * Indicates whether AHB and PHY clocks are synchronous to - * each other. - * * 1'b0: No - * * 1'b1: Yes - * This bit is tied to 1. - * @rsttype: Reset Style for Clocked always Blocks in RTL (RstType) - * * 1'b0: Asynchronous reset is used in the core - * * 1'b1: Synchronous reset is used in the core - * @optfeature: Optional Features Removed (OptFeature) - * Indicates whether the User ID register, GPIO interface ports, - * and SOF toggle and counter ports were removed for gate count - * optimization. - * @vendor_control_interface_support: Vendor Control Interface Support - * * 1'b0: Vendor Control Interface is not available on the core. - * * 1'b1: Vendor Control Interface is available. - * @i2c_selection: I2C Selection - * * 1'b0: I2C Interface is not available on the core. - * * 1'b1: I2C Interface is available on the core. - * @otgen: OTG Function Enabled (OtgEn) - * The application uses this bit to indicate the O2P USB core's - * OTG capabilities. - * * 1'b0: Not OTG capable - * * 1'b1: OTG Capable - * @pktsizewidth: Width of Packet Size Counters (PktSizeWidth) - * * 3'b000: 4 bits - * * 3'b001: 5 bits - * * 3'b010: 6 bits - * * 3'b011: 7 bits - * * 3'b100: 8 bits - * * 3'b101: 9 bits - * * 3'b110: 10 bits - * * Others: Reserved - * @xfersizewidth: Width of Transfer Size Counters (XferSizeWidth) - * * 4'b0000: 11 bits - * * 4'b0001: 12 bits - * - ... - * * 4'b1000: 19 bits - * * Others: Reserved - */ - struct cvmx_usbcx_ghwcfg3_s { - __BITFIELD_FIELD(u32 dfifodepth : 16, - __BITFIELD_FIELD(u32 reserved_13_15 : 3, - __BITFIELD_FIELD(u32 ahbphysync : 1, - __BITFIELD_FIELD(u32 rsttype : 1, - __BITFIELD_FIELD(u32 optfeature : 1, - __BITFIELD_FIELD(u32 vendor_control_interface_support : 1, - __BITFIELD_FIELD(u32 i2c_selection : 1, - __BITFIELD_FIELD(u32 otgen : 1, - __BITFIELD_FIELD(u32 pktsizewidth : 3, - __BITFIELD_FIELD(u32 xfersizewidth : 4, - ;)))))))))) - } s; -}; - -/** - * cvmx_usbc#_gintmsk - * - * Core Interrupt Mask Register (GINTMSK) - * - * This register works with the Core Interrupt register to interrupt the - * application. When an interrupt bit is masked, the interrupt associated with - * that bit will not be generated. However, the Core Interrupt (GINTSTS) - * register bit corresponding to that interrupt will still be set. - * Mask interrupt: 1'b0, Unmask interrupt: 1'b1 - */ -union cvmx_usbcx_gintmsk { - u32 u32; - /** - * struct cvmx_usbcx_gintmsk_s - * @wkupintmsk: Resume/Remote Wakeup Detected Interrupt Mask - * (WkUpIntMsk) - * @sessreqintmsk: Session Request/New Session Detected Interrupt Mask - * (SessReqIntMsk) - * @disconnintmsk: Disconnect Detected Interrupt Mask (DisconnIntMsk) - * @conidstschngmsk: Connector ID Status Change Mask (ConIDStsChngMsk) - * @ptxfempmsk: Periodic TxFIFO Empty Mask (PTxFEmpMsk) - * @hchintmsk: Host Channels Interrupt Mask (HChIntMsk) - * @prtintmsk: Host Port Interrupt Mask (PrtIntMsk) - * @fetsuspmsk: Data Fetch Suspended Mask (FetSuspMsk) - * @incomplpmsk: Incomplete Periodic Transfer Mask (incomplPMsk) - * Incomplete Isochronous OUT Transfer Mask - * (incompISOOUTMsk) - * @incompisoinmsk: Incomplete Isochronous IN Transfer Mask - * (incompISOINMsk) - * @oepintmsk: OUT Endpoints Interrupt Mask (OEPIntMsk) - * @inepintmsk: IN Endpoints Interrupt Mask (INEPIntMsk) - * @epmismsk: Endpoint Mismatch Interrupt Mask (EPMisMsk) - * @eopfmsk: End of Periodic Frame Interrupt Mask (EOPFMsk) - * @isooutdropmsk: Isochronous OUT Packet Dropped Interrupt Mask - * (ISOOutDropMsk) - * @enumdonemsk: Enumeration Done Mask (EnumDoneMsk) - * @usbrstmsk: USB Reset Mask (USBRstMsk) - * @usbsuspmsk: USB Suspend Mask (USBSuspMsk) - * @erlysuspmsk: Early Suspend Mask (ErlySuspMsk) - * @i2cint: I2C Interrupt Mask (I2CINT) - * @ulpickintmsk: ULPI Carkit Interrupt Mask (ULPICKINTMsk) - * I2C Carkit Interrupt Mask (I2CCKINTMsk) - * @goutnakeffmsk: Global OUT NAK Effective Mask (GOUTNakEffMsk) - * @ginnakeffmsk: Global Non-Periodic IN NAK Effective Mask - * (GINNakEffMsk) - * @nptxfempmsk: Non-Periodic TxFIFO Empty Mask (NPTxFEmpMsk) - * @rxflvlmsk: Receive FIFO Non-Empty Mask (RxFLvlMsk) - * @sofmsk: Start of (micro)Frame Mask (SofMsk) - * @otgintmsk: OTG Interrupt Mask (OTGIntMsk) - * @modemismsk: Mode Mismatch Interrupt Mask (ModeMisMsk) - */ - struct cvmx_usbcx_gintmsk_s { - __BITFIELD_FIELD(u32 wkupintmsk : 1, - __BITFIELD_FIELD(u32 sessreqintmsk : 1, - __BITFIELD_FIELD(u32 disconnintmsk : 1, - __BITFIELD_FIELD(u32 conidstschngmsk : 1, - __BITFIELD_FIELD(u32 reserved_27_27 : 1, - __BITFIELD_FIELD(u32 ptxfempmsk : 1, - __BITFIELD_FIELD(u32 hchintmsk : 1, - __BITFIELD_FIELD(u32 prtintmsk : 1, - __BITFIELD_FIELD(u32 reserved_23_23 : 1, - __BITFIELD_FIELD(u32 fetsuspmsk : 1, - __BITFIELD_FIELD(u32 incomplpmsk : 1, - __BITFIELD_FIELD(u32 incompisoinmsk : 1, - __BITFIELD_FIELD(u32 oepintmsk : 1, - __BITFIELD_FIELD(u32 inepintmsk : 1, - __BITFIELD_FIELD(u32 epmismsk : 1, - __BITFIELD_FIELD(u32 reserved_16_16 : 1, - __BITFIELD_FIELD(u32 eopfmsk : 1, - __BITFIELD_FIELD(u32 isooutdropmsk : 1, - __BITFIELD_FIELD(u32 enumdonemsk : 1, - __BITFIELD_FIELD(u32 usbrstmsk : 1, - __BITFIELD_FIELD(u32 usbsuspmsk : 1, - __BITFIELD_FIELD(u32 erlysuspmsk : 1, - __BITFIELD_FIELD(u32 i2cint : 1, - __BITFIELD_FIELD(u32 ulpickintmsk : 1, - __BITFIELD_FIELD(u32 goutnakeffmsk : 1, - __BITFIELD_FIELD(u32 ginnakeffmsk : 1, - __BITFIELD_FIELD(u32 nptxfempmsk : 1, - __BITFIELD_FIELD(u32 rxflvlmsk : 1, - __BITFIELD_FIELD(u32 sofmsk : 1, - __BITFIELD_FIELD(u32 otgintmsk : 1, - __BITFIELD_FIELD(u32 modemismsk : 1, - __BITFIELD_FIELD(u32 reserved_0_0 : 1, - ;)))))))))))))))))))))))))))))))) - } s; -}; - -/** - * cvmx_usbc#_gintsts - * - * Core Interrupt Register (GINTSTS) - * - * This register interrupts the application for system-level events in the - * current mode of operation (Device mode or Host mode). It is shown in - * Interrupt. Some of the bits in this register are valid only in Host mode, - * while others are valid in Device mode only. This register also indicates the - * current mode of operation. In order to clear the interrupt status bits of - * type R_SS_WC, the application must write 1'b1 into the bit. The FIFO status - * interrupts are read only; once software reads from or writes to the FIFO - * while servicing these interrupts, FIFO interrupt conditions are cleared - * automatically. - */ -union cvmx_usbcx_gintsts { - u32 u32; - /** - * struct cvmx_usbcx_gintsts_s - * @wkupint: Resume/Remote Wakeup Detected Interrupt (WkUpInt) - * In Device mode, this interrupt is asserted when a resume is - * detected on the USB. In Host mode, this interrupt is asserted - * when a remote wakeup is detected on the USB. - * For more information on how to use this interrupt, see "Partial - * Power-Down and Clock Gating Programming Model" on - * page 353. - * @sessreqint: Session Request/New Session Detected Interrupt - * (SessReqInt) - * In Host mode, this interrupt is asserted when a session request - * is detected from the device. In Device mode, this interrupt is - * asserted when the utmiotg_bvalid signal goes high. - * For more information on how to use this interrupt, see "Partial - * Power-Down and Clock Gating Programming Model" on - * page 353. - * @disconnint: Disconnect Detected Interrupt (DisconnInt) - * Asserted when a device disconnect is detected. - * @conidstschng: Connector ID Status Change (ConIDStsChng) - * The core sets this bit when there is a change in connector ID - * status. - * @ptxfemp: Periodic TxFIFO Empty (PTxFEmp) - * Asserted when the Periodic Transmit FIFO is either half or - * completely empty and there is space for at least one entry to be - * written in the Periodic Request Queue. The half or completely - * empty status is determined by the Periodic TxFIFO Empty Level - * bit in the Core AHB Configuration register - * (GAHBCFG.PTxFEmpLvl). - * @hchint: Host Channels Interrupt (HChInt) - * The core sets this bit to indicate that an interrupt is pending - * on one of the channels of the core (in Host mode). The - * application must read the Host All Channels Interrupt (HAINT) - * register to determine the exact number of the channel on which - * the interrupt occurred, and then read the corresponding Host - * Channel-n Interrupt (HCINTn) register to determine the exact - * cause of the interrupt. The application must clear the - * appropriate status bit in the HCINTn register to clear this bit. - * @prtint: Host Port Interrupt (PrtInt) - * The core sets this bit to indicate a change in port status of - * one of the O2P USB core ports in Host mode. The application must - * read the Host Port Control and Status (HPRT) register to - * determine the exact event that caused this interrupt. The - * application must clear the appropriate status bit in the Host - * Port Control and Status register to clear this bit. - * @fetsusp: Data Fetch Suspended (FetSusp) - * This interrupt is valid only in DMA mode. This interrupt - * indicates that the core has stopped fetching data for IN - * endpoints due to the unavailability of TxFIFO space or Request - * Queue space. This interrupt is used by the application for an - * endpoint mismatch algorithm. - * @incomplp: Incomplete Periodic Transfer (incomplP) - * In Host mode, the core sets this interrupt bit when there are - * incomplete periodic transactions still pending which are - * scheduled for the current microframe. - * Incomplete Isochronous OUT Transfer (incompISOOUT) - * The Device mode, the core sets this interrupt to indicate that - * there is at least one isochronous OUT endpoint on which the - * transfer is not completed in the current microframe. This - * interrupt is asserted along with the End of Periodic Frame - * Interrupt (EOPF) bit in this register. - * @incompisoin: Incomplete Isochronous IN Transfer (incompISOIN) - * The core sets this interrupt to indicate that there is at least - * one isochronous IN endpoint on which the transfer is not - * completed in the current microframe. This interrupt is asserted - * along with the End of Periodic Frame Interrupt (EOPF) bit in - * this register. - * @oepint: OUT Endpoints Interrupt (OEPInt) - * The core sets this bit to indicate that an interrupt is pending - * on one of the OUT endpoints of the core (in Device mode). The - * application must read the Device All Endpoints Interrupt - * (DAINT) register to determine the exact number of the OUT - * endpoint on which the interrupt occurred, and then read the - * corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) - * register to determine the exact cause of the interrupt. The - * application must clear the appropriate status bit in the - * corresponding DOEPINTn register to clear this bit. - * @iepint: IN Endpoints Interrupt (IEPInt) - * The core sets this bit to indicate that an interrupt is pending - * on one of the IN endpoints of the core (in Device mode). The - * application must read the Device All Endpoints Interrupt - * (DAINT) register to determine the exact number of the IN - * endpoint on which the interrupt occurred, and then read the - * corresponding Device IN Endpoint-n Interrupt (DIEPINTn) - * register to determine the exact cause of the interrupt. The - * application must clear the appropriate status bit in the - * corresponding DIEPINTn register to clear this bit. - * @epmis: Endpoint Mismatch Interrupt (EPMis) - * Indicates that an IN token has been received for a non-periodic - * endpoint, but the data for another endpoint is present in the - * top of the Non-Periodic Transmit FIFO and the IN endpoint - * mismatch count programmed by the application has expired. - * @eopf: End of Periodic Frame Interrupt (EOPF) - * Indicates that the period specified in the Periodic Frame - * Interval field of the Device Configuration register - * (DCFG.PerFrInt) has been reached in the current microframe. - * @isooutdrop: Isochronous OUT Packet Dropped Interrupt (ISOOutDrop) - * The core sets this bit when it fails to write an isochronous OUT - * packet into the RxFIFO because the RxFIFO doesn't have - * enough space to accommodate a maximum packet size packet - * for the isochronous OUT endpoint. - * @enumdone: Enumeration Done (EnumDone) - * The core sets this bit to indicate that speed enumeration is - * complete. The application must read the Device Status (DSTS) - * register to obtain the enumerated speed. - * @usbrst: USB Reset (USBRst) - * The core sets this bit to indicate that a reset is detected on - * the USB. - * @usbsusp: USB Suspend (USBSusp) - * The core sets this bit to indicate that a suspend was detected - * on the USB. The core enters the Suspended state when there - * is no activity on the phy_line_state_i signal for an extended - * period of time. - * @erlysusp: Early Suspend (ErlySusp) - * The core sets this bit to indicate that an Idle state has been - * detected on the USB for 3 ms. - * @i2cint: I2C Interrupt (I2CINT) - * This bit is always 0x0. - * @ulpickint: ULPI Carkit Interrupt (ULPICKINT) - * This bit is always 0x0. - * @goutnakeff: Global OUT NAK Effective (GOUTNakEff) - * Indicates that the Set Global OUT NAK bit in the Device Control - * register (DCTL.SGOUTNak), set by the application, has taken - * effect in the core. This bit can be cleared by writing the Clear - * Global OUT NAK bit in the Device Control register - * (DCTL.CGOUTNak). - * @ginnakeff: Global IN Non-Periodic NAK Effective (GINNakEff) - * Indicates that the Set Global Non-Periodic IN NAK bit in the - * Device Control register (DCTL.SGNPInNak), set by the - * application, has taken effect in the core. That is, the core has - * sampled the Global IN NAK bit set by the application. This bit - * can be cleared by clearing the Clear Global Non-Periodic IN - * NAK bit in the Device Control register (DCTL.CGNPInNak). - * This interrupt does not necessarily mean that a NAK handshake - * is sent out on the USB. The STALL bit takes precedence over - * the NAK bit. - * @nptxfemp: Non-Periodic TxFIFO Empty (NPTxFEmp) - * This interrupt is asserted when the Non-Periodic TxFIFO is - * either half or completely empty, and there is space for at least - * one entry to be written to the Non-Periodic Transmit Request - * Queue. The half or completely empty status is determined by - * the Non-Periodic TxFIFO Empty Level bit in the Core AHB - * Configuration register (GAHBCFG.NPTxFEmpLvl). - * @rxflvl: RxFIFO Non-Empty (RxFLvl) - * Indicates that there is at least one packet pending to be read - * from the RxFIFO. - * @sof: Start of (micro)Frame (Sof) - * In Host mode, the core sets this bit to indicate that an SOF - * (FS), micro-SOF (HS), or Keep-Alive (LS) is transmitted on the - * USB. The application must write a 1 to this bit to clear the - * interrupt. - * In Device mode, in the core sets this bit to indicate that an - * SOF token has been received on the USB. The application can read - * the Device Status register to get the current (micro)frame - * number. This interrupt is seen only when the core is operating - * at either HS or FS. - * @otgint: OTG Interrupt (OTGInt) - * The core sets this bit to indicate an OTG protocol event. The - * application must read the OTG Interrupt Status (GOTGINT) - * register to determine the exact event that caused this - * interrupt. The application must clear the appropriate status bit - * in the GOTGINT register to clear this bit. - * @modemis: Mode Mismatch Interrupt (ModeMis) - * The core sets this bit when the application is trying to access: - * * A Host mode register, when the core is operating in Device - * mode - * * A Device mode register, when the core is operating in Host - * mode - * The register access is completed on the AHB with an OKAY - * response, but is ignored by the core internally and doesn't - * affect the operation of the core. - * @curmod: Current Mode of Operation (CurMod) - * Indicates the current mode of operation. - * * 1'b0: Device mode - * * 1'b1: Host mode - */ - struct cvmx_usbcx_gintsts_s { - __BITFIELD_FIELD(u32 wkupint : 1, - __BITFIELD_FIELD(u32 sessreqint : 1, - __BITFIELD_FIELD(u32 disconnint : 1, - __BITFIELD_FIELD(u32 conidstschng : 1, - __BITFIELD_FIELD(u32 reserved_27_27 : 1, - __BITFIELD_FIELD(u32 ptxfemp : 1, - __BITFIELD_FIELD(u32 hchint : 1, - __BITFIELD_FIELD(u32 prtint : 1, - __BITFIELD_FIELD(u32 reserved_23_23 : 1, - __BITFIELD_FIELD(u32 fetsusp : 1, - __BITFIELD_FIELD(u32 incomplp : 1, - __BITFIELD_FIELD(u32 incompisoin : 1, - __BITFIELD_FIELD(u32 oepint : 1, - __BITFIELD_FIELD(u32 iepint : 1, - __BITFIELD_FIELD(u32 epmis : 1, - __BITFIELD_FIELD(u32 reserved_16_16 : 1, - __BITFIELD_FIELD(u32 eopf : 1, - __BITFIELD_FIELD(u32 isooutdrop : 1, - __BITFIELD_FIELD(u32 enumdone : 1, - __BITFIELD_FIELD(u32 usbrst : 1, - __BITFIELD_FIELD(u32 usbsusp : 1, - __BITFIELD_FIELD(u32 erlysusp : 1, - __BITFIELD_FIELD(u32 i2cint : 1, - __BITFIELD_FIELD(u32 ulpickint : 1, - __BITFIELD_FIELD(u32 goutnakeff : 1, - __BITFIELD_FIELD(u32 ginnakeff : 1, - __BITFIELD_FIELD(u32 nptxfemp : 1, - __BITFIELD_FIELD(u32 rxflvl : 1, - __BITFIELD_FIELD(u32 sof : 1, - __BITFIELD_FIELD(u32 otgint : 1, - __BITFIELD_FIELD(u32 modemis : 1, - __BITFIELD_FIELD(u32 curmod : 1, - ;)))))))))))))))))))))))))))))))) - } s; -}; - -/** - * cvmx_usbc#_gnptxfsiz - * - * Non-Periodic Transmit FIFO Size Register (GNPTXFSIZ) - * - * The application can program the RAM size and the memory start address for the - * Non-Periodic TxFIFO. - */ -union cvmx_usbcx_gnptxfsiz { - u32 u32; - /** - * struct cvmx_usbcx_gnptxfsiz_s - * @nptxfdep: Non-Periodic TxFIFO Depth (NPTxFDep) - * This value is in terms of 32-bit words. - * Minimum value is 16 - * Maximum value is 32768 - * @nptxfstaddr: Non-Periodic Transmit RAM Start Address (NPTxFStAddr) - * This field contains the memory start address for Non-Periodic - * Transmit FIFO RAM. - */ - struct cvmx_usbcx_gnptxfsiz_s { - __BITFIELD_FIELD(u32 nptxfdep : 16, - __BITFIELD_FIELD(u32 nptxfstaddr : 16, - ;)) - } s; -}; - -/** - * cvmx_usbc#_gnptxsts - * - * Non-Periodic Transmit FIFO/Queue Status Register (GNPTXSTS) - * - * This read-only register contains the free space information for the - * Non-Periodic TxFIFO and the Non-Periodic Transmit Request Queue. - */ -union cvmx_usbcx_gnptxsts { - u32 u32; - /** - * struct cvmx_usbcx_gnptxsts_s - * @nptxqtop: Top of the Non-Periodic Transmit Request Queue (NPTxQTop) - * Entry in the Non-Periodic Tx Request Queue that is currently - * being processed by the MAC. - * * Bits [30:27]: Channel/endpoint number - * * Bits [26:25]: - * - 2'b00: IN/OUT token - * - 2'b01: Zero-length transmit packet (device IN/host OUT) - * - 2'b10: PING/CSPLIT token - * - 2'b11: Channel halt command - * * Bit [24]: Terminate (last entry for selected channel/endpoint) - * @nptxqspcavail: Non-Periodic Transmit Request Queue Space Available - * (NPTxQSpcAvail) - * Indicates the amount of free space available in the Non- - * Periodic Transmit Request Queue. This queue holds both IN - * and OUT requests in Host mode. Device mode has only IN - * requests. - * * 8'h0: Non-Periodic Transmit Request Queue is full - * * 8'h1: 1 location available - * * 8'h2: 2 locations available - * * n: n locations available (0..8) - * * Others: Reserved - * @nptxfspcavail: Non-Periodic TxFIFO Space Avail (NPTxFSpcAvail) - * Indicates the amount of free space available in the Non- - * Periodic TxFIFO. - * Values are in terms of 32-bit words. - * * 16'h0: Non-Periodic TxFIFO is full - * * 16'h1: 1 word available - * * 16'h2: 2 words available - * * 16'hn: n words available (where 0..32768) - * * 16'h8000: 32768 words available - * * Others: Reserved - */ - struct cvmx_usbcx_gnptxsts_s { - __BITFIELD_FIELD(u32 reserved_31_31 : 1, - __BITFIELD_FIELD(u32 nptxqtop : 7, - __BITFIELD_FIELD(u32 nptxqspcavail : 8, - __BITFIELD_FIELD(u32 nptxfspcavail : 16, - ;)))) - } s; -}; - -/** - * cvmx_usbc#_grstctl - * - * Core Reset Register (GRSTCTL) - * - * The application uses this register to reset various hardware features inside - * the core. - */ -union cvmx_usbcx_grstctl { - u32 u32; - /** - * struct cvmx_usbcx_grstctl_s - * @ahbidle: AHB Master Idle (AHBIdle) - * Indicates that the AHB Master State Machine is in the IDLE - * condition. - * @dmareq: DMA Request Signal (DMAReq) - * Indicates that the DMA request is in progress. Used for debug. - * @txfnum: TxFIFO Number (TxFNum) - * This is the FIFO number that must be flushed using the TxFIFO - * Flush bit. This field must not be changed until the core clears - * the TxFIFO Flush bit. - * * 5'h0: Non-Periodic TxFIFO flush - * * 5'h1: Periodic TxFIFO 1 flush in Device mode or Periodic - * TxFIFO flush in Host mode - * * 5'h2: Periodic TxFIFO 2 flush in Device mode - * - ... - * * 5'hF: Periodic TxFIFO 15 flush in Device mode - * * 5'h10: Flush all the Periodic and Non-Periodic TxFIFOs in the - * core - * @txfflsh: TxFIFO Flush (TxFFlsh) - * This bit selectively flushes a single or all transmit FIFOs, but - * cannot do so if the core is in the midst of a transaction. - * The application must only write this bit after checking that the - * core is neither writing to the TxFIFO nor reading from the - * TxFIFO. - * The application must wait until the core clears this bit before - * performing any operations. This bit takes 8 clocks (of phy_clk - * or hclk, whichever is slower) to clear. - * @rxfflsh: RxFIFO Flush (RxFFlsh) - * The application can flush the entire RxFIFO using this bit, but - * must first ensure that the core is not in the middle of a - * transaction. - * The application must only write to this bit after checking that - * the core is neither reading from the RxFIFO nor writing to the - * RxFIFO. - * The application must wait until the bit is cleared before - * performing any other operations. This bit will take 8 clocks - * (slowest of PHY or AHB clock) to clear. - * @intknqflsh: IN Token Sequence Learning Queue Flush (INTknQFlsh) - * The application writes this bit to flush the IN Token Sequence - * Learning Queue. - * @frmcntrrst: Host Frame Counter Reset (FrmCntrRst) - * The application writes this bit to reset the (micro)frame number - * counter inside the core. When the (micro)frame counter is reset, - * the subsequent SOF sent out by the core will have a - * (micro)frame number of 0. - * @hsftrst: HClk Soft Reset (HSftRst) - * The application uses this bit to flush the control logic in the - * AHB Clock domain. Only AHB Clock Domain pipelines are reset. - * * FIFOs are not flushed with this bit. - * * All state machines in the AHB clock domain are reset to the - * Idle state after terminating the transactions on the AHB, - * following the protocol. - * * CSR control bits used by the AHB clock domain state - * machines are cleared. - * * To clear this interrupt, status mask bits that control the - * interrupt status and are generated by the AHB clock domain - * state machine are cleared. - * * Because interrupt status bits are not cleared, the application - * can get the status of any core events that occurred after it set - * this bit. - * This is a self-clearing bit that the core clears after all - * necessary logic is reset in the core. This may take several - * clocks, depending on the core's current state. - * @csftrst: Core Soft Reset (CSftRst) - * Resets the hclk and phy_clock domains as follows: - * * Clears the interrupts and all the CSR registers except the - * following register bits: - * - PCGCCTL.RstPdwnModule - * - PCGCCTL.GateHclk - * - PCGCCTL.PwrClmp - * - PCGCCTL.StopPPhyLPwrClkSelclk - * - GUSBCFG.PhyLPwrClkSel - * - GUSBCFG.DDRSel - * - GUSBCFG.PHYSel - * - GUSBCFG.FSIntf - * - GUSBCFG.ULPI_UTMI_Sel - * - GUSBCFG.PHYIf - * - HCFG.FSLSPclkSel - * - DCFG.DevSpd - * * All module state machines (except the AHB Slave Unit) are - * reset to the IDLE state, and all the transmit FIFOs and the - * receive FIFO are flushed. - * * Any transactions on the AHB Master are terminated as soon - * as possible, after gracefully completing the last data phase of - * an AHB transfer. Any transactions on the USB are terminated - * immediately. - * The application can write to this bit any time it wants to reset - * the core. This is a self-clearing bit and the core clears this - * bit after all the necessary logic is reset in the core, which - * may take several clocks, depending on the current state of the - * core. Once this bit is cleared software should wait at least 3 - * PHY clocks before doing any access to the PHY domain - * (synchronization delay). Software should also should check that - * bit 31 of this register is 1 (AHB Master is IDLE) before - * starting any operation. - * Typically software reset is used during software development - * and also when you dynamically change the PHY selection bits - * in the USB configuration registers listed above. When you - * change the PHY, the corresponding clock for the PHY is - * selected and used in the PHY domain. Once a new clock is - * selected, the PHY domain has to be reset for proper operation. - */ - struct cvmx_usbcx_grstctl_s { - __BITFIELD_FIELD(u32 ahbidle : 1, - __BITFIELD_FIELD(u32 dmareq : 1, - __BITFIELD_FIELD(u32 reserved_11_29 : 19, - __BITFIELD_FIELD(u32 txfnum : 5, - __BITFIELD_FIELD(u32 txfflsh : 1, - __BITFIELD_FIELD(u32 rxfflsh : 1, - __BITFIELD_FIELD(u32 intknqflsh : 1, - __BITFIELD_FIELD(u32 frmcntrrst : 1, - __BITFIELD_FIELD(u32 hsftrst : 1, - __BITFIELD_FIELD(u32 csftrst : 1, - ;)))))))))) - } s; -}; - -/** - * cvmx_usbc#_grxfsiz - * - * Receive FIFO Size Register (GRXFSIZ) - * - * The application can program the RAM size that must be allocated to the - * RxFIFO. - */ -union cvmx_usbcx_grxfsiz { - u32 u32; - /** - * struct cvmx_usbcx_grxfsiz_s - * @rxfdep: RxFIFO Depth (RxFDep) - * This value is in terms of 32-bit words. - * * Minimum value is 16 - * * Maximum value is 32768 - */ - struct cvmx_usbcx_grxfsiz_s { - __BITFIELD_FIELD(u32 reserved_16_31 : 16, - __BITFIELD_FIELD(u32 rxfdep : 16, - ;)) - } s; -}; - -/** - * cvmx_usbc#_grxstsph - * - * Receive Status Read and Pop Register, Host Mode (GRXSTSPH) - * - * A read to the Receive Status Read and Pop register returns and additionally - * pops the top data entry out of the RxFIFO. - * This Description is only valid when the core is in Host Mode. For Device Mode - * use USBC_GRXSTSPD instead. - * NOTE: GRXSTSPH and GRXSTSPD are physically the same register and share the - * same offset in the O2P USB core. The offset difference shown in this - * document is for software clarity and is actually ignored by the - * hardware. - */ -union cvmx_usbcx_grxstsph { - u32 u32; - /** - * struct cvmx_usbcx_grxstsph_s - * @pktsts: Packet Status (PktSts) - * Indicates the status of the received packet - * * 4'b0010: IN data packet received - * * 4'b0011: IN transfer completed (triggers an interrupt) - * * 4'b0101: Data toggle error (triggers an interrupt) - * * 4'b0111: Channel halted (triggers an interrupt) - * * Others: Reserved - * @dpid: Data PID (DPID) - * * 2'b00: DATA0 - * * 2'b10: DATA1 - * * 2'b01: DATA2 - * * 2'b11: MDATA - * @bcnt: Byte Count (BCnt) - * Indicates the byte count of the received IN data packet - * @chnum: Channel Number (ChNum) - * Indicates the channel number to which the current received - * packet belongs. - */ - struct cvmx_usbcx_grxstsph_s { - __BITFIELD_FIELD(u32 reserved_21_31 : 11, - __BITFIELD_FIELD(u32 pktsts : 4, - __BITFIELD_FIELD(u32 dpid : 2, - __BITFIELD_FIELD(u32 bcnt : 11, - __BITFIELD_FIELD(u32 chnum : 4, - ;))))) - } s; -}; - -/** - * cvmx_usbc#_gusbcfg - * - * Core USB Configuration Register (GUSBCFG) - * - * This register can be used to configure the core after power-on or a changing - * to Host mode or Device mode. It contains USB and USB-PHY related - * configuration parameters. The application must program this register before - * starting any transactions on either the AHB or the USB. Do not make changes - * to this register after the initial programming. - */ -union cvmx_usbcx_gusbcfg { - u32 u32; - /** - * struct cvmx_usbcx_gusbcfg_s - * @otgi2csel: UTMIFS or I2C Interface Select (OtgI2CSel) - * This bit is always 0x0. - * @phylpwrclksel: PHY Low-Power Clock Select (PhyLPwrClkSel) - * Software should set this bit to 0x0. - * Selects either 480-MHz or 48-MHz (low-power) PHY mode. In - * FS and LS modes, the PHY can usually operate on a 48-MHz - * clock to save power. - * * 1'b0: 480-MHz Internal PLL clock - * * 1'b1: 48-MHz External Clock - * In 480 MHz mode, the UTMI interface operates at either 60 or - * 30-MHz, depending upon whether 8- or 16-bit data width is - * selected. In 48-MHz mode, the UTMI interface operates at 48 - * MHz in FS mode and at either 48 or 6 MHz in LS mode - * (depending on the PHY vendor). - * This bit drives the utmi_fsls_low_power core output signal, and - * is valid only for UTMI+ PHYs. - * @usbtrdtim: USB Turnaround Time (USBTrdTim) - * Sets the turnaround time in PHY clocks. - * Specifies the response time for a MAC request to the Packet - * FIFO Controller (PFC) to fetch data from the DFIFO (SPRAM). - * This must be programmed to 0x5. - * @hnpcap: HNP-Capable (HNPCap) - * This bit is always 0x0. - * @srpcap: SRP-Capable (SRPCap) - * This bit is always 0x0. - * @ddrsel: ULPI DDR Select (DDRSel) - * Software should set this bit to 0x0. - * @physel: USB 2.0 High-Speed PHY or USB 1.1 Full-Speed Serial - * Software should set this bit to 0x0. - * @fsintf: Full-Speed Serial Interface Select (FSIntf) - * Software should set this bit to 0x0. - * @ulpi_utmi_sel: ULPI or UTMI+ Select (ULPI_UTMI_Sel) - * This bit is always 0x0. - * @phyif: PHY Interface (PHYIf) - * This bit is always 0x1. - * @toutcal: HS/FS Timeout Calibration (TOutCal) - * The number of PHY clocks that the application programs in this - * field is added to the high-speed/full-speed interpacket timeout - * duration in the core to account for any additional delays - * introduced by the PHY. This may be required, since the delay - * introduced by the PHY in generating the linestate condition may - * vary from one PHY to another. - * The USB standard timeout value for high-speed operation is - * 736 to 816 (inclusive) bit times. The USB standard timeout - * value for full-speed operation is 16 to 18 (inclusive) bit - * times. The application must program this field based on the - * speed of enumeration. The number of bit times added per PHY - * clock are: - * High-speed operation: - * * One 30-MHz PHY clock = 16 bit times - * * One 60-MHz PHY clock = 8 bit times - * Full-speed operation: - * * One 30-MHz PHY clock = 0.4 bit times - * * One 60-MHz PHY clock = 0.2 bit times - * * One 48-MHz PHY clock = 0.25 bit times - */ - struct cvmx_usbcx_gusbcfg_s { - __BITFIELD_FIELD(u32 reserved_17_31 : 15, - __BITFIELD_FIELD(u32 otgi2csel : 1, - __BITFIELD_FIELD(u32 phylpwrclksel : 1, - __BITFIELD_FIELD(u32 reserved_14_14 : 1, - __BITFIELD_FIELD(u32 usbtrdtim : 4, - __BITFIELD_FIELD(u32 hnpcap : 1, - __BITFIELD_FIELD(u32 srpcap : 1, - __BITFIELD_FIELD(u32 ddrsel : 1, - __BITFIELD_FIELD(u32 physel : 1, - __BITFIELD_FIELD(u32 fsintf : 1, - __BITFIELD_FIELD(u32 ulpi_utmi_sel : 1, - __BITFIELD_FIELD(u32 phyif : 1, - __BITFIELD_FIELD(u32 toutcal : 3, - ;))))))))))))) - } s; -}; - -/** - * cvmx_usbc#_haint - * - * Host All Channels Interrupt Register (HAINT) - * - * When a significant event occurs on a channel, the Host All Channels Interrupt - * register interrupts the application using the Host Channels Interrupt bit of - * the Core Interrupt register (GINTSTS.HChInt). This is shown in Interrupt. - * There is one interrupt bit per channel, up to a maximum of 16 bits. Bits in - * this register are set and cleared when the application sets and clears bits - * in the corresponding Host Channel-n Interrupt register. - */ -union cvmx_usbcx_haint { - u32 u32; - /** - * struct cvmx_usbcx_haint_s - * @haint: Channel Interrupts (HAINT) - * One bit per channel: Bit 0 for Channel 0, bit 15 for Channel 15 - */ - struct cvmx_usbcx_haint_s { - __BITFIELD_FIELD(u32 reserved_16_31 : 16, - __BITFIELD_FIELD(u32 haint : 16, - ;)) - } s; -}; - -/** - * cvmx_usbc#_haintmsk - * - * Host All Channels Interrupt Mask Register (HAINTMSK) - * - * The Host All Channel Interrupt Mask register works with the Host All Channel - * Interrupt register to interrupt the application when an event occurs on a - * channel. There is one interrupt mask bit per channel, up to a maximum of 16 - * bits. - * Mask interrupt: 1'b0 Unmask interrupt: 1'b1 - */ -union cvmx_usbcx_haintmsk { - u32 u32; - /** - * struct cvmx_usbcx_haintmsk_s - * @haintmsk: Channel Interrupt Mask (HAINTMsk) - * One bit per channel: Bit 0 for channel 0, bit 15 for channel 15 - */ - struct cvmx_usbcx_haintmsk_s { - __BITFIELD_FIELD(u32 reserved_16_31 : 16, - __BITFIELD_FIELD(u32 haintmsk : 16, - ;)) - } s; -}; - -/** - * cvmx_usbc#_hcchar# - * - * Host Channel-n Characteristics Register (HCCHAR) - * - */ -union cvmx_usbcx_hccharx { - u32 u32; - /** - * struct cvmx_usbcx_hccharx_s - * @chena: Channel Enable (ChEna) - * This field is set by the application and cleared by the OTG - * host. - * * 1'b0: Channel disabled - * * 1'b1: Channel enabled - * @chdis: Channel Disable (ChDis) - * The application sets this bit to stop transmitting/receiving - * data on a channel, even before the transfer for that channel is - * complete. The application must wait for the Channel Disabled - * interrupt before treating the channel as disabled. - * @oddfrm: Odd Frame (OddFrm) - * This field is set (reset) by the application to indicate that - * the OTG host must perform a transfer in an odd (micro)frame. - * This field is applicable for only periodic (isochronous and - * interrupt) transactions. - * * 1'b0: Even (micro)frame - * * 1'b1: Odd (micro)frame - * @devaddr: Device Address (DevAddr) - * This field selects the specific device serving as the data - * source or sink. - * @ec: Multi Count (MC) / Error Count (EC) - * When the Split Enable bit of the Host Channel-n Split Control - * register (HCSPLTn.SpltEna) is reset (1'b0), this field indicates - * to the host the number of transactions that should be executed - * per microframe for this endpoint. - * * 2'b00: Reserved. This field yields undefined results. - * * 2'b01: 1 transaction - * * 2'b10: 2 transactions to be issued for this endpoint per - * microframe - * * 2'b11: 3 transactions to be issued for this endpoint per - * microframe - * When HCSPLTn.SpltEna is set (1'b1), this field indicates the - * number of immediate retries to be performed for a periodic split - * transactions on transaction errors. This field must be set to at - * least 2'b01. - * @eptype: Endpoint Type (EPType) - * Indicates the transfer type selected. - * * 2'b00: Control - * * 2'b01: Isochronous - * * 2'b10: Bulk - * * 2'b11: Interrupt - * @lspddev: Low-Speed Device (LSpdDev) - * This field is set by the application to indicate that this - * channel is communicating to a low-speed device. - * @epdir: Endpoint Direction (EPDir) - * Indicates whether the transaction is IN or OUT. - * * 1'b0: OUT - * * 1'b1: IN - * @epnum: Endpoint Number (EPNum) - * Indicates the endpoint number on the device serving as the - * data source or sink. - * @mps: Maximum Packet Size (MPS) - * Indicates the maximum packet size of the associated endpoint. - */ - struct cvmx_usbcx_hccharx_s { - __BITFIELD_FIELD(u32 chena : 1, - __BITFIELD_FIELD(u32 chdis : 1, - __BITFIELD_FIELD(u32 oddfrm : 1, - __BITFIELD_FIELD(u32 devaddr : 7, - __BITFIELD_FIELD(u32 ec : 2, - __BITFIELD_FIELD(u32 eptype : 2, - __BITFIELD_FIELD(u32 lspddev : 1, - __BITFIELD_FIELD(u32 reserved_16_16 : 1, - __BITFIELD_FIELD(u32 epdir : 1, - __BITFIELD_FIELD(u32 epnum : 4, - __BITFIELD_FIELD(u32 mps : 11, - ;))))))))))) - } s; -}; - -/** - * cvmx_usbc#_hcfg - * - * Host Configuration Register (HCFG) - * - * This register configures the core after power-on. Do not make changes to this - * register after initializing the host. - */ -union cvmx_usbcx_hcfg { - u32 u32; - /** - * struct cvmx_usbcx_hcfg_s - * @fslssupp: FS- and LS-Only Support (FSLSSupp) - * The application uses this bit to control the core's enumeration - * speed. Using this bit, the application can make the core - * enumerate as a FS host, even if the connected device supports - * HS traffic. Do not make changes to this field after initial - * programming. - * * 1'b0: HS/FS/LS, based on the maximum speed supported by - * the connected device - * * 1'b1: FS/LS-only, even if the connected device can support HS - * @fslspclksel: FS/LS PHY Clock Select (FSLSPclkSel) - * When the core is in FS Host mode - * * 2'b00: PHY clock is running at 30/60 MHz - * * 2'b01: PHY clock is running at 48 MHz - * * Others: Reserved - * When the core is in LS Host mode - * * 2'b00: PHY clock is running at 30/60 MHz. When the - * UTMI+/ULPI PHY Low Power mode is not selected, use - * 30/60 MHz. - * * 2'b01: PHY clock is running at 48 MHz. When the UTMI+ - * PHY Low Power mode is selected, use 48MHz if the PHY - * supplies a 48 MHz clock during LS mode. - * * 2'b10: PHY clock is running at 6 MHz. In USB 1.1 FS mode, - * use 6 MHz when the UTMI+ PHY Low Power mode is - * selected and the PHY supplies a 6 MHz clock during LS - * mode. If you select a 6 MHz clock during LS mode, you must - * do a soft reset. - * * 2'b11: Reserved - */ - struct cvmx_usbcx_hcfg_s { - __BITFIELD_FIELD(u32 reserved_3_31 : 29, - __BITFIELD_FIELD(u32 fslssupp : 1, - __BITFIELD_FIELD(u32 fslspclksel : 2, - ;))) - } s; -}; - -/** - * cvmx_usbc#_hcint# - * - * Host Channel-n Interrupt Register (HCINT) - * - * This register indicates the status of a channel with respect to USB- and - * AHB-related events. The application must read this register when the Host - * Channels Interrupt bit of the Core Interrupt register (GINTSTS.HChInt) is - * set. Before the application can read this register, it must first read - * the Host All Channels Interrupt (HAINT) register to get the exact channel - * number for the Host Channel-n Interrupt register. The application must clear - * the appropriate bit in this register to clear the corresponding bits in the - * HAINT and GINTSTS registers. - */ -union cvmx_usbcx_hcintx { - u32 u32; - /** - * struct cvmx_usbcx_hcintx_s - * @datatglerr: Data Toggle Error (DataTglErr) - * @frmovrun: Frame Overrun (FrmOvrun) - * @bblerr: Babble Error (BblErr) - * @xacterr: Transaction Error (XactErr) - * @nyet: NYET Response Received Interrupt (NYET) - * @ack: ACK Response Received Interrupt (ACK) - * @nak: NAK Response Received Interrupt (NAK) - * @stall: STALL Response Received Interrupt (STALL) - * @ahberr: This bit is always 0x0. - * @chhltd: Channel Halted (ChHltd) - * Indicates the transfer completed abnormally either because of - * any USB transaction error or in response to disable request by - * the application. - * @xfercompl: Transfer Completed (XferCompl) - * Transfer completed normally without any errors. - */ - struct cvmx_usbcx_hcintx_s { - __BITFIELD_FIELD(u32 reserved_11_31 : 21, - __BITFIELD_FIELD(u32 datatglerr : 1, - __BITFIELD_FIELD(u32 frmovrun : 1, - __BITFIELD_FIELD(u32 bblerr : 1, - __BITFIELD_FIELD(u32 xacterr : 1, - __BITFIELD_FIELD(u32 nyet : 1, - __BITFIELD_FIELD(u32 ack : 1, - __BITFIELD_FIELD(u32 nak : 1, - __BITFIELD_FIELD(u32 stall : 1, - __BITFIELD_FIELD(u32 ahberr : 1, - __BITFIELD_FIELD(u32 chhltd : 1, - __BITFIELD_FIELD(u32 xfercompl : 1, - ;)))))))))))) - } s; -}; - -/** - * cvmx_usbc#_hcintmsk# - * - * Host Channel-n Interrupt Mask Register (HCINTMSKn) - * - * This register reflects the mask for each channel status described in the - * previous section. - * Mask interrupt: 1'b0 Unmask interrupt: 1'b1 - */ -union cvmx_usbcx_hcintmskx { - u32 u32; - /** - * struct cvmx_usbcx_hcintmskx_s - * @datatglerrmsk: Data Toggle Error Mask (DataTglErrMsk) - * @frmovrunmsk: Frame Overrun Mask (FrmOvrunMsk) - * @bblerrmsk: Babble Error Mask (BblErrMsk) - * @xacterrmsk: Transaction Error Mask (XactErrMsk) - * @nyetmsk: NYET Response Received Interrupt Mask (NyetMsk) - * @ackmsk: ACK Response Received Interrupt Mask (AckMsk) - * @nakmsk: NAK Response Received Interrupt Mask (NakMsk) - * @stallmsk: STALL Response Received Interrupt Mask (StallMsk) - * @ahberrmsk: AHB Error Mask (AHBErrMsk) - * @chhltdmsk: Channel Halted Mask (ChHltdMsk) - * @xfercomplmsk: Transfer Completed Mask (XferComplMsk) - */ - struct cvmx_usbcx_hcintmskx_s { - __BITFIELD_FIELD(u32 reserved_11_31 : 21, - __BITFIELD_FIELD(u32 datatglerrmsk : 1, - __BITFIELD_FIELD(u32 frmovrunmsk : 1, - __BITFIELD_FIELD(u32 bblerrmsk : 1, - __BITFIELD_FIELD(u32 xacterrmsk : 1, - __BITFIELD_FIELD(u32 nyetmsk : 1, - __BITFIELD_FIELD(u32 ackmsk : 1, - __BITFIELD_FIELD(u32 nakmsk : 1, - __BITFIELD_FIELD(u32 stallmsk : 1, - __BITFIELD_FIELD(u32 ahberrmsk : 1, - __BITFIELD_FIELD(u32 chhltdmsk : 1, - __BITFIELD_FIELD(u32 xfercomplmsk : 1, - ;)))))))))))) - } s; -}; - -/** - * cvmx_usbc#_hcsplt# - * - * Host Channel-n Split Control Register (HCSPLT) - * - */ -union cvmx_usbcx_hcspltx { - u32 u32; - /** - * struct cvmx_usbcx_hcspltx_s - * @spltena: Split Enable (SpltEna) - * The application sets this field to indicate that this channel is - * enabled to perform split transactions. - * @compsplt: Do Complete Split (CompSplt) - * The application sets this field to request the OTG host to - * perform a complete split transaction. - * @xactpos: Transaction Position (XactPos) - * This field is used to determine whether to send all, first, - * middle, or last payloads with each OUT transaction. - * * 2'b11: All. This is the entire data payload is of this - * transaction (which is less than or equal to 188 bytes). - * * 2'b10: Begin. This is the first data payload of this - * transaction (which is larger than 188 bytes). - * * 2'b00: Mid. This is the middle payload of this transaction - * (which is larger than 188 bytes). - * * 2'b01: End. This is the last payload of this transaction - * (which is larger than 188 bytes). - * @hubaddr: Hub Address (HubAddr) - * This field holds the device address of the transaction - * translator's hub. - * @prtaddr: Port Address (PrtAddr) - * This field is the port number of the recipient transaction - * translator. - */ - struct cvmx_usbcx_hcspltx_s { - __BITFIELD_FIELD(u32 spltena : 1, - __BITFIELD_FIELD(u32 reserved_17_30 : 14, - __BITFIELD_FIELD(u32 compsplt : 1, - __BITFIELD_FIELD(u32 xactpos : 2, - __BITFIELD_FIELD(u32 hubaddr : 7, - __BITFIELD_FIELD(u32 prtaddr : 7, - ;)))))) - } s; -}; - -/** - * cvmx_usbc#_hctsiz# - * - * Host Channel-n Transfer Size Register (HCTSIZ) - * - */ -union cvmx_usbcx_hctsizx { - u32 u32; - /** - * struct cvmx_usbcx_hctsizx_s - * @dopng: Do Ping (DoPng) - * Setting this field to 1 directs the host to do PING protocol. - * @pid: PID (Pid) - * The application programs this field with the type of PID to use - * for the initial transaction. The host will maintain this field - * for the rest of the transfer. - * * 2'b00: DATA0 - * * 2'b01: DATA2 - * * 2'b10: DATA1 - * * 2'b11: MDATA (non-control)/SETUP (control) - * @pktcnt: Packet Count (PktCnt) - * This field is programmed by the application with the expected - * number of packets to be transmitted (OUT) or received (IN). - * The host decrements this count on every successful - * transmission or reception of an OUT/IN packet. Once this count - * reaches zero, the application is interrupted to indicate normal - * completion. - * @xfersize: Transfer Size (XferSize) - * For an OUT, this field is the number of data bytes the host will - * send during the transfer. - * For an IN, this field is the buffer size that the application - * has reserved for the transfer. The application is expected to - * program this field as an integer multiple of the maximum packet - * size for IN transactions (periodic and non-periodic). - */ - struct cvmx_usbcx_hctsizx_s { - __BITFIELD_FIELD(u32 dopng : 1, - __BITFIELD_FIELD(u32 pid : 2, - __BITFIELD_FIELD(u32 pktcnt : 10, - __BITFIELD_FIELD(u32 xfersize : 19, - ;)))) - } s; -}; - -/** - * cvmx_usbc#_hfir - * - * Host Frame Interval Register (HFIR) - * - * This register stores the frame interval information for the current speed to - * which the O2P USB core has enumerated. - */ -union cvmx_usbcx_hfir { - u32 u32; - /** - * struct cvmx_usbcx_hfir_s - * @frint: Frame Interval (FrInt) - * The value that the application programs to this field specifies - * the interval between two consecutive SOFs (FS) or micro- - * SOFs (HS) or Keep-Alive tokens (HS). This field contains the - * number of PHY clocks that constitute the required frame - * interval. The default value set in this field for a FS operation - * when the PHY clock frequency is 60 MHz. The application can - * write a value to this register only after the Port Enable bit of - * the Host Port Control and Status register (HPRT.PrtEnaPort) - * has been set. If no value is programmed, the core calculates - * the value based on the PHY clock specified in the FS/LS PHY - * Clock Select field of the Host Configuration register - * (HCFG.FSLSPclkSel). Do not change the value of this field - * after the initial configuration. - * * 125 us (PHY clock frequency for HS) - * * 1 ms (PHY clock frequency for FS/LS) - */ - struct cvmx_usbcx_hfir_s { - __BITFIELD_FIELD(u32 reserved_16_31 : 16, - __BITFIELD_FIELD(u32 frint : 16, - ;)) - } s; -}; - -/** - * cvmx_usbc#_hfnum - * - * Host Frame Number/Frame Time Remaining Register (HFNUM) - * - * This register indicates the current frame number. - * It also indicates the time remaining (in terms of the number of PHY clocks) - * in the current (micro)frame. - */ -union cvmx_usbcx_hfnum { - u32 u32; - /** - * struct cvmx_usbcx_hfnum_s - * @frrem: Frame Time Remaining (FrRem) - * Indicates the amount of time remaining in the current - * microframe (HS) or frame (FS/LS), in terms of PHY clocks. - * This field decrements on each PHY clock. When it reaches - * zero, this field is reloaded with the value in the Frame - * Interval register and a new SOF is transmitted on the USB. - * @frnum: Frame Number (FrNum) - * This field increments when a new SOF is transmitted on the - * USB, and is reset to 0 when it reaches 16'h3FFF. - */ - struct cvmx_usbcx_hfnum_s { - __BITFIELD_FIELD(u32 frrem : 16, - __BITFIELD_FIELD(u32 frnum : 16, - ;)) - } s; -}; - -/** - * cvmx_usbc#_hprt - * - * Host Port Control and Status Register (HPRT) - * - * This register is available in both Host and Device modes. - * Currently, the OTG Host supports only one port. - * A single register holds USB port-related information such as USB reset, - * enable, suspend, resume, connect status, and test mode for each port. The - * R_SS_WC bits in this register can trigger an interrupt to the application - * through the Host Port Interrupt bit of the Core Interrupt register - * (GINTSTS.PrtInt). On a Port Interrupt, the application must read this - * register and clear the bit that caused the interrupt. For the R_SS_WC bits, - * the application must write a 1 to the bit to clear the interrupt. - */ -union cvmx_usbcx_hprt { - u32 u32; - /** - * struct cvmx_usbcx_hprt_s - * @prtspd: Port Speed (PrtSpd) - * Indicates the speed of the device attached to this port. - * * 2'b00: High speed - * * 2'b01: Full speed - * * 2'b10: Low speed - * * 2'b11: Reserved - * @prttstctl: Port Test Control (PrtTstCtl) - * The application writes a nonzero value to this field to put - * the port into a Test mode, and the corresponding pattern is - * signaled on the port. - * * 4'b0000: Test mode disabled - * * 4'b0001: Test_J mode - * * 4'b0010: Test_K mode - * * 4'b0011: Test_SE0_NAK mode - * * 4'b0100: Test_Packet mode - * * 4'b0101: Test_Force_Enable - * * Others: Reserved - * PrtSpd must be zero (i.e. the interface must be in high-speed - * mode) to use the PrtTstCtl test modes. - * @prtpwr: Port Power (PrtPwr) - * The application uses this field to control power to this port, - * and the core clears this bit on an overcurrent condition. - * * 1'b0: Power off - * * 1'b1: Power on - * @prtlnsts: Port Line Status (PrtLnSts) - * Indicates the current logic level USB data lines - * * Bit [10]: Logic level of D- - * * Bit [11]: Logic level of D+ - * @prtrst: Port Reset (PrtRst) - * When the application sets this bit, a reset sequence is - * started on this port. The application must time the reset - * period and clear this bit after the reset sequence is - * complete. - * * 1'b0: Port not in reset - * * 1'b1: Port in reset - * The application must leave this bit set for at least a - * minimum duration mentioned below to start a reset on the - * port. The application can leave it set for another 10 ms in - * addition to the required minimum duration, before clearing - * the bit, even though there is no maximum limit set by the - * USB standard. - * * High speed: 50 ms - * * Full speed/Low speed: 10 ms - * @prtsusp: Port Suspend (PrtSusp) - * The application sets this bit to put this port in Suspend - * mode. The core only stops sending SOFs when this is set. - * To stop the PHY clock, the application must set the Port - * Clock Stop bit, which will assert the suspend input pin of - * the PHY. - * The read value of this bit reflects the current suspend - * status of the port. This bit is cleared by the core after a - * remote wakeup signal is detected or the application sets - * the Port Reset bit or Port Resume bit in this register or the - * Resume/Remote Wakeup Detected Interrupt bit or - * Disconnect Detected Interrupt bit in the Core Interrupt - * register (GINTSTS.WkUpInt or GINTSTS.DisconnInt, - * respectively). - * * 1'b0: Port not in Suspend mode - * * 1'b1: Port in Suspend mode - * @prtres: Port Resume (PrtRes) - * The application sets this bit to drive resume signaling on - * the port. The core continues to drive the resume signal - * until the application clears this bit. - * If the core detects a USB remote wakeup sequence, as - * indicated by the Port Resume/Remote Wakeup Detected - * Interrupt bit of the Core Interrupt register - * (GINTSTS.WkUpInt), the core starts driving resume - * signaling without application intervention and clears this bit - * when it detects a disconnect condition. The read value of - * this bit indicates whether the core is currently driving - * resume signaling. - * * 1'b0: No resume driven - * * 1'b1: Resume driven - * @prtovrcurrchng: Port Overcurrent Change (PrtOvrCurrChng) - * The core sets this bit when the status of the Port - * Overcurrent Active bit (bit 4) in this register changes. - * @prtovrcurract: Port Overcurrent Active (PrtOvrCurrAct) - * Indicates the overcurrent condition of the port. - * * 1'b0: No overcurrent condition - * * 1'b1: Overcurrent condition - * @prtenchng: Port Enable/Disable Change (PrtEnChng) - * The core sets this bit when the status of the Port Enable bit - * [2] of this register changes. - * @prtena: Port Enable (PrtEna) - * A port is enabled only by the core after a reset sequence, - * and is disabled by an overcurrent condition, a disconnect - * condition, or by the application clearing this bit. The - * application cannot set this bit by a register write. It can only - * clear it to disable the port. This bit does not trigger any - * interrupt to the application. - * * 1'b0: Port disabled - * * 1'b1: Port enabled - * @prtconndet: Port Connect Detected (PrtConnDet) - * The core sets this bit when a device connection is detected - * to trigger an interrupt to the application using the Host Port - * Interrupt bit of the Core Interrupt register (GINTSTS.PrtInt). - * The application must write a 1 to this bit to clear the - * interrupt. - * @prtconnsts: Port Connect Status (PrtConnSts) - * * 0: No device is attached to the port. - * * 1: A device is attached to the port. - */ - struct cvmx_usbcx_hprt_s { - __BITFIELD_FIELD(u32 reserved_19_31 : 13, - __BITFIELD_FIELD(u32 prtspd : 2, - __BITFIELD_FIELD(u32 prttstctl : 4, - __BITFIELD_FIELD(u32 prtpwr : 1, - __BITFIELD_FIELD(u32 prtlnsts : 2, - __BITFIELD_FIELD(u32 reserved_9_9 : 1, - __BITFIELD_FIELD(u32 prtrst : 1, - __BITFIELD_FIELD(u32 prtsusp : 1, - __BITFIELD_FIELD(u32 prtres : 1, - __BITFIELD_FIELD(u32 prtovrcurrchng : 1, - __BITFIELD_FIELD(u32 prtovrcurract : 1, - __BITFIELD_FIELD(u32 prtenchng : 1, - __BITFIELD_FIELD(u32 prtena : 1, - __BITFIELD_FIELD(u32 prtconndet : 1, - __BITFIELD_FIELD(u32 prtconnsts : 1, - ;))))))))))))))) - } s; -}; - -/** - * cvmx_usbc#_hptxfsiz - * - * Host Periodic Transmit FIFO Size Register (HPTXFSIZ) - * - * This register holds the size and the memory start address of the Periodic - * TxFIFO, as shown in Figures 310 and 311. - */ -union cvmx_usbcx_hptxfsiz { - u32 u32; - /** - * struct cvmx_usbcx_hptxfsiz_s - * @ptxfsize: Host Periodic TxFIFO Depth (PTxFSize) - * This value is in terms of 32-bit words. - * * Minimum value is 16 - * * Maximum value is 32768 - * @ptxfstaddr: Host Periodic TxFIFO Start Address (PTxFStAddr) - */ - struct cvmx_usbcx_hptxfsiz_s { - __BITFIELD_FIELD(u32 ptxfsize : 16, - __BITFIELD_FIELD(u32 ptxfstaddr : 16, - ;)) - } s; -}; - -/** - * cvmx_usbc#_hptxsts - * - * Host Periodic Transmit FIFO/Queue Status Register (HPTXSTS) - * - * This read-only register contains the free space information for the Periodic - * TxFIFO and the Periodic Transmit Request Queue - */ -union cvmx_usbcx_hptxsts { - u32 u32; - /** - * struct cvmx_usbcx_hptxsts_s - * @ptxqtop: Top of the Periodic Transmit Request Queue (PTxQTop) - * This indicates the entry in the Periodic Tx Request Queue that - * is currently being processes by the MAC. - * This register is used for debugging. - * * Bit [31]: Odd/Even (micro)frame - * - 1'b0: send in even (micro)frame - * - 1'b1: send in odd (micro)frame - * * Bits [30:27]: Channel/endpoint number - * * Bits [26:25]: Type - * - 2'b00: IN/OUT - * - 2'b01: Zero-length packet - * - 2'b10: CSPLIT - * - 2'b11: Disable channel command - * * Bit [24]: Terminate (last entry for the selected - * channel/endpoint) - * @ptxqspcavail: Periodic Transmit Request Queue Space Available - * (PTxQSpcAvail) - * Indicates the number of free locations available to be written - * in the Periodic Transmit Request Queue. This queue holds both - * IN and OUT requests. - * * 8'h0: Periodic Transmit Request Queue is full - * * 8'h1: 1 location available - * * 8'h2: 2 locations available - * * n: n locations available (0..8) - * * Others: Reserved - * @ptxfspcavail: Periodic Transmit Data FIFO Space Available - * (PTxFSpcAvail) - * Indicates the number of free locations available to be written - * to in the Periodic TxFIFO. - * Values are in terms of 32-bit words - * * 16'h0: Periodic TxFIFO is full - * * 16'h1: 1 word available - * * 16'h2: 2 words available - * * 16'hn: n words available (where 0..32768) - * * 16'h8000: 32768 words available - * * Others: Reserved - */ - struct cvmx_usbcx_hptxsts_s { - __BITFIELD_FIELD(u32 ptxqtop : 8, - __BITFIELD_FIELD(u32 ptxqspcavail : 8, - __BITFIELD_FIELD(u32 ptxfspcavail : 16, - ;))) - } s; -}; - -/** - * cvmx_usbn#_clk_ctl - * - * USBN_CLK_CTL = USBN's Clock Control - * - * This register is used to control the frequency of the hclk and the - * hreset and phy_rst signals. - */ -union cvmx_usbnx_clk_ctl { - u64 u64; - /** - * struct cvmx_usbnx_clk_ctl_s - * @divide2: The 'hclk' used by the USB subsystem is derived - * from the eclk. - * Also see the field DIVIDE. DIVIDE2<1> must currently - * be zero because it is not implemented, so the maximum - * ratio of eclk/hclk is currently 16. - * The actual divide number for hclk is: - * (DIVIDE2 + 1) * (DIVIDE + 1) - * @hclk_rst: When this field is '0' the HCLK-DIVIDER used to - * generate the hclk in the USB Subsystem is held - * in reset. This bit must be set to '0' before - * changing the value os DIVIDE in this register. - * The reset to the HCLK_DIVIDERis also asserted - * when core reset is asserted. - * @p_x_on: Force USB-PHY on during suspend. - * '1' USB-PHY XO block is powered-down during - * suspend. - * '0' USB-PHY XO block is powered-up during - * suspend. - * The value of this field must be set while POR is - * active. - * @p_rtype: PHY reference clock type - * On CN50XX/CN52XX/CN56XX the values are: - * '0' The USB-PHY uses a 12MHz crystal as a clock source - * at the USB_XO and USB_XI pins. - * '1' Reserved. - * '2' The USB_PHY uses 12/24/48MHz 2.5V board clock at the - * USB_XO pin. USB_XI should be tied to ground in this - * case. - * '3' Reserved. - * On CN3xxx bits 14 and 15 are p_xenbn and p_rclk and values are: - * '0' Reserved. - * '1' Reserved. - * '2' The PHY PLL uses the XO block output as a reference. - * The XO block uses an external clock supplied on the - * XO pin. USB_XI should be tied to ground for this - * usage. - * '3' The XO block uses the clock from a crystal. - * @p_com_on: '0' Force USB-PHY XO Bias, Bandgap and PLL to - * remain powered in Suspend Mode. - * '1' The USB-PHY XO Bias, Bandgap and PLL are - * powered down in suspend mode. - * The value of this field must be set while POR is - * active. - * @p_c_sel: Phy clock speed select. - * Selects the reference clock / crystal frequency. - * '11': Reserved - * '10': 48 MHz (reserved when a crystal is used) - * '01': 24 MHz (reserved when a crystal is used) - * '00': 12 MHz - * The value of this field must be set while POR is - * active. - * NOTE: if a crystal is used as a reference clock, - * this field must be set to 12 MHz. - * @cdiv_byp: Used to enable the bypass input to the USB_CLK_DIV. - * @sd_mode: Scaledown mode for the USBC. Control timing events - * in the USBC, for normal operation this must be '0'. - * @s_bist: Starts bist on the hclk memories, during the '0' - * to '1' transition. - * @por: Power On Reset for the PHY. - * Resets all the PHYS registers and state machines. - * @enable: When '1' allows the generation of the hclk. When - * '0' the hclk will not be generated. SEE DIVIDE - * field of this register. - * @prst: When this field is '0' the reset associated with - * the phy_clk functionality in the USB Subsystem is - * help in reset. This bit should not be set to '1' - * until the time it takes 6 clocks (hclk or phy_clk, - * whichever is slower) has passed. Under normal - * operation once this bit is set to '1' it should not - * be set to '0'. - * @hrst: When this field is '0' the reset associated with - * the hclk functioanlity in the USB Subsystem is - * held in reset.This bit should not be set to '1' - * until 12ms after phy_clk is stable. Under normal - * operation, once this bit is set to '1' it should - * not be set to '0'. - * @divide: The frequency of 'hclk' used by the USB subsystem - * is the eclk frequency divided by the value of - * (DIVIDE2 + 1) * (DIVIDE + 1), also see the field - * DIVIDE2 of this register. - * The hclk frequency should be less than 125Mhz. - * After writing a value to this field the SW should - * read the field for the value written. - * The ENABLE field of this register should not be set - * until AFTER this field is set and then read. - */ - struct cvmx_usbnx_clk_ctl_s { - __BITFIELD_FIELD(u64 reserved_20_63 : 44, - __BITFIELD_FIELD(u64 divide2 : 2, - __BITFIELD_FIELD(u64 hclk_rst : 1, - __BITFIELD_FIELD(u64 p_x_on : 1, - __BITFIELD_FIELD(u64 p_rtype : 2, - __BITFIELD_FIELD(u64 p_com_on : 1, - __BITFIELD_FIELD(u64 p_c_sel : 2, - __BITFIELD_FIELD(u64 cdiv_byp : 1, - __BITFIELD_FIELD(u64 sd_mode : 2, - __BITFIELD_FIELD(u64 s_bist : 1, - __BITFIELD_FIELD(u64 por : 1, - __BITFIELD_FIELD(u64 enable : 1, - __BITFIELD_FIELD(u64 prst : 1, - __BITFIELD_FIELD(u64 hrst : 1, - __BITFIELD_FIELD(u64 divide : 3, - ;))))))))))))))) - } s; -}; - -/** - * cvmx_usbn#_usbp_ctl_status - * - * USBN_USBP_CTL_STATUS = USBP Control And Status Register - * - * Contains general control and status information for the USBN block. - */ -union cvmx_usbnx_usbp_ctl_status { - u64 u64; - /** - * struct cvmx_usbnx_usbp_ctl_status_s - * @txrisetune: HS Transmitter Rise/Fall Time Adjustment - * @txvreftune: HS DC Voltage Level Adjustment - * @txfslstune: FS/LS Source Impedance Adjustment - * @txhsxvtune: Transmitter High-Speed Crossover Adjustment - * @sqrxtune: Squelch Threshold Adjustment - * @compdistune: Disconnect Threshold Adjustment - * @otgtune: VBUS Valid Threshold Adjustment - * @otgdisable: OTG Block Disable - * @portreset: Per_Port Reset - * @drvvbus: Drive VBUS - * @lsbist: Low-Speed BIST Enable. - * @fsbist: Full-Speed BIST Enable. - * @hsbist: High-Speed BIST Enable. - * @bist_done: PHY Bist Done. - * Asserted at the end of the PHY BIST sequence. - * @bist_err: PHY Bist Error. - * Indicates an internal error was detected during - * the BIST sequence. - * @tdata_out: PHY Test Data Out. - * Presents either internally generated signals or - * test register contents, based upon the value of - * test_data_out_sel. - * @siddq: Drives the USBP (USB-PHY) SIDDQ input. - * Normally should be set to zero. - * When customers have no intent to use USB PHY - * interface, they should: - * - still provide 3.3V to USB_VDD33, and - * - tie USB_REXT to 3.3V supply, and - * - set USBN*_USBP_CTL_STATUS[SIDDQ]=1 - * @txpreemphasistune: HS Transmitter Pre-Emphasis Enable - * @dma_bmode: When set to 1 the L2C DMA address will be updated - * with byte-counts between packets. When set to 0 - * the L2C DMA address is incremented to the next - * 4-byte aligned address after adding byte-count. - * @usbc_end: Bigendian input to the USB Core. This should be - * set to '0' for operation. - * @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP. - * @tclk: PHY Test Clock, used to load TDATA_IN to the USBP. - * @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY. - * This signal enables the pull-down resistance on - * the D+ line. '1' pull down-resistance is connected - * to D+/ '0' pull down resistance is not connected - * to D+. When an A/B device is acting as a host - * (downstream-facing port), dp_pulldown and - * dm_pulldown are enabled. This must not toggle - * during normal operation. - * @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY. - * This signal enables the pull-down resistance on - * the D- line. '1' pull down-resistance is connected - * to D-. '0' pull down resistance is not connected - * to D-. When an A/B device is acting as a host - * (downstream-facing port), dp_pulldown and - * dm_pulldown are enabled. This must not toggle - * during normal operation. - * @hst_mode: When '0' the USB is acting as HOST, when '1' - * USB is acting as device. This field needs to be - * set while the USB is in reset. - * @tuning: Transmitter Tuning for High-Speed Operation. - * Tunes the current supply and rise/fall output - * times for high-speed operation. - * [20:19] == 11: Current supply increased - * approximately 9% - * [20:19] == 10: Current supply increased - * approximately 4.5% - * [20:19] == 01: Design default. - * [20:19] == 00: Current supply decreased - * approximately 4.5% - * [22:21] == 11: Rise and fall times are increased. - * [22:21] == 10: Design default. - * [22:21] == 01: Rise and fall times are decreased. - * [22:21] == 00: Rise and fall times are decreased - * further as compared to the 01 setting. - * @tx_bs_enh: Transmit Bit Stuffing on [15:8]. - * Enables or disables bit stuffing on data[15:8] - * when bit-stuffing is enabled. - * @tx_bs_en: Transmit Bit Stuffing on [7:0]. - * Enables or disables bit stuffing on data[7:0] - * when bit-stuffing is enabled. - * @loop_enb: PHY Loopback Test Enable. - * '1': During data transmission the receive is - * enabled. - * '0': During data transmission the receive is - * disabled. - * Must be '0' for normal operation. - * @vtest_enb: Analog Test Pin Enable. - * '1' The PHY's analog_test pin is enabled for the - * input and output of applicable analog test signals. - * '0' THe analog_test pin is disabled. - * @bist_enb: Built-In Self Test Enable. - * Used to activate BIST in the PHY. - * @tdata_sel: Test Data Out Select. - * '1' test_data_out[3:0] (PHY) register contents - * are output. '0' internally generated signals are - * output. - * @taddr_in: Mode Address for Test Interface. - * Specifies the register address for writing to or - * reading from the PHY test interface register. - * @tdata_in: Internal Testing Register Input Data and Select - * This is a test bus. Data is present on [3:0], - * and its corresponding select (enable) is present - * on bits [7:4]. - * @ate_reset: Reset input from automatic test equipment. - * This is a test signal. When the USB Core is - * powered up (not in Susned Mode), an automatic - * tester can use this to disable phy_clock and - * free_clk, then re-enable them with an aligned - * phase. - * '1': The phy_clk and free_clk outputs are - * disabled. "0": The phy_clock and free_clk outputs - * are available within a specific period after the - * de-assertion. - */ - struct cvmx_usbnx_usbp_ctl_status_s { - __BITFIELD_FIELD(u64 txrisetune : 1, - __BITFIELD_FIELD(u64 txvreftune : 4, - __BITFIELD_FIELD(u64 txfslstune : 4, - __BITFIELD_FIELD(u64 txhsxvtune : 2, - __BITFIELD_FIELD(u64 sqrxtune : 3, - __BITFIELD_FIELD(u64 compdistune : 3, - __BITFIELD_FIELD(u64 otgtune : 3, - __BITFIELD_FIELD(u64 otgdisable : 1, - __BITFIELD_FIELD(u64 portreset : 1, - __BITFIELD_FIELD(u64 drvvbus : 1, - __BITFIELD_FIELD(u64 lsbist : 1, - __BITFIELD_FIELD(u64 fsbist : 1, - __BITFIELD_FIELD(u64 hsbist : 1, - __BITFIELD_FIELD(u64 bist_done : 1, - __BITFIELD_FIELD(u64 bist_err : 1, - __BITFIELD_FIELD(u64 tdata_out : 4, - __BITFIELD_FIELD(u64 siddq : 1, - __BITFIELD_FIELD(u64 txpreemphasistune : 1, - __BITFIELD_FIELD(u64 dma_bmode : 1, - __BITFIELD_FIELD(u64 usbc_end : 1, - __BITFIELD_FIELD(u64 usbp_bist : 1, - __BITFIELD_FIELD(u64 tclk : 1, - __BITFIELD_FIELD(u64 dp_pulld : 1, - __BITFIELD_FIELD(u64 dm_pulld : 1, - __BITFIELD_FIELD(u64 hst_mode : 1, - __BITFIELD_FIELD(u64 tuning : 4, - __BITFIELD_FIELD(u64 tx_bs_enh : 1, - __BITFIELD_FIELD(u64 tx_bs_en : 1, - __BITFIELD_FIELD(u64 loop_enb : 1, - __BITFIELD_FIELD(u64 vtest_enb : 1, - __BITFIELD_FIELD(u64 bist_enb : 1, - __BITFIELD_FIELD(u64 tdata_sel : 1, - __BITFIELD_FIELD(u64 taddr_in : 4, - __BITFIELD_FIELD(u64 tdata_in : 8, - __BITFIELD_FIELD(u64 ate_reset : 1, - ;))))))))))))))))))))))))))))))))))) - } s; -}; - -#endif /* __OCTEON_HCD_H__ */ From 25dde2435ad659b59154335604162abfcf059dd5 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Wed, 11 Dec 2019 12:12:30 -0600 Subject: [PATCH 091/353] staging: qlge: Fix CHECK extra blank lines in many files Fix CHECK: Please don't use multiple blank lines in qlge.h, qlge_dbg.c, qlge_ethtool.c, qlge_main.c, and qlge_mpi.c Signed-off-by: Scott Schafer Link: https://lore.kernel.org/r/9387760ae35bdeb606dc03ca9dd167f5214cd3a8.1576086080.git.schaferjscott@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/qlge/qlge.h | 1 - drivers/staging/qlge/qlge_dbg.c | 4 ---- drivers/staging/qlge/qlge_ethtool.c | 1 - drivers/staging/qlge/qlge_main.c | 2 -- drivers/staging/qlge/qlge_mpi.c | 5 ----- 5 files changed, 13 deletions(-) diff --git a/drivers/staging/qlge/qlge.h b/drivers/staging/qlge/qlge.h index 57884aac308f..4bc5d5fce9bf 100644 --- a/drivers/staging/qlge/qlge.h +++ b/drivers/staging/qlge/qlge.h @@ -63,7 +63,6 @@ #define UDELAY_COUNT 3 #define UDELAY_DELAY 100 - #define TX_DESC_PER_IOCB 8 #if ((MAX_SKB_FRAGS - TX_DESC_PER_IOCB) + 2) > 0 diff --git a/drivers/staging/qlge/qlge_dbg.c b/drivers/staging/qlge/qlge_dbg.c index aac20db565fa..d56f2205effa 100644 --- a/drivers/staging/qlge/qlge_dbg.c +++ b/drivers/staging/qlge/qlge_dbg.c @@ -142,7 +142,6 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev, u32 *direct_ptr, temp; u32 *indirect_ptr; - /* The XAUI needs to be read out per port */ status = ql_read_other_func_serdes_reg(qdev, XG_SERDES_XAUI_HSS_PCS_START, &temp); @@ -297,7 +296,6 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev, ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr, xfi_direct_valid, xfi_indirect_valid); - /* Get XAUI_XFI_HSS_PLL register block. */ if (qdev->func & 1) { direct_ptr = @@ -1227,7 +1225,6 @@ static void ql_gen_reg_dump(struct ql_adapter *qdev, { int i, status; - memset(&(mpi_coredump->mpi_global_header), 0, sizeof(struct mpi_coredump_global_header)); mpi_coredump->mpi_global_header.cookie = MPI_COREDUMP_COOKIE; @@ -1238,7 +1235,6 @@ static void ql_gen_reg_dump(struct ql_adapter *qdev, strncpy(mpi_coredump->mpi_global_header.id_string, "MPI Coredump", sizeof(mpi_coredump->mpi_global_header.id_string)); - /* segment 16 */ ql_build_coredump_seg_header(&mpi_coredump->misc_nic_seg_hdr, MISC_NIC_INFO_SEG_NUM, diff --git a/drivers/staging/qlge/qlge_ethtool.c b/drivers/staging/qlge/qlge_ethtool.c index d661218e1aa2..3a4060f03e21 100644 --- a/drivers/staging/qlge/qlge_ethtool.c +++ b/drivers/staging/qlge/qlge_ethtool.c @@ -32,7 +32,6 @@ #include #include - #include "qlge.h" struct ql_stats { diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c index 29861f01ca26..b2f826822a51 100644 --- a/drivers/staging/qlge/qlge_main.c +++ b/drivers/staging/qlge/qlge_main.c @@ -207,7 +207,6 @@ static int ql_wait_cfg(struct ql_adapter *qdev, u32 bit) return -ETIMEDOUT; } - /* Used to issue init control blocks to hw. Maps control block, * sets address, triggers download, waits for completion. */ @@ -2641,7 +2640,6 @@ static netdev_tx_t qlge_send(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_OK; } - static void ql_free_shadow_space(struct ql_adapter *qdev) { if (qdev->rx_ring_shadow_reg_area) { diff --git a/drivers/staging/qlge/qlge_mpi.c b/drivers/staging/qlge/qlge_mpi.c index 9e422bbbb6ab..843b32240a73 100644 --- a/drivers/staging/qlge/qlge_mpi.c +++ b/drivers/staging/qlge/qlge_mpi.c @@ -544,7 +544,6 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) if (status) goto end; - /* If we're generating a system error, then there's nothing * to wait for. */ @@ -730,7 +729,6 @@ int ql_mb_set_port_cfg(struct ql_adapter *qdev) mbcp->mbox_in[1] = qdev->link_config; mbcp->mbox_in[2] = qdev->max_frame_size; - status = ql_mailbox_command(qdev, mbcp); if (status) return status; @@ -768,7 +766,6 @@ static int ql_mb_dump_ram(struct ql_adapter *qdev, u64 req_dma, u32 addr, mbcp->mbox_in[7] = LSW(MSD(req_dma)); mbcp->mbox_in[8] = MSW(addr); - status = ql_mailbox_command(qdev, mbcp); if (status) return status; @@ -850,7 +847,6 @@ int ql_mb_wol_mode(struct ql_adapter *qdev, u32 wol) mbcp->mbox_in[0] = MB_CMD_SET_WOL_MODE; mbcp->mbox_in[1] = wol; - status = ql_mailbox_command(qdev, mbcp); if (status) return status; @@ -965,7 +961,6 @@ int ql_mb_set_led_cfg(struct ql_adapter *qdev, u32 led_config) mbcp->mbox_in[0] = MB_CMD_SET_LED_CFG; mbcp->mbox_in[1] = led_config; - status = ql_mailbox_command(qdev, mbcp); if (status) return status; From 1b998958b301fb7f7e33212e84dc162a711fad81 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Wed, 11 Dec 2019 12:12:31 -0600 Subject: [PATCH 092/353] staging: qlge: Fix CHECK: Alignment should match open parenthesis Fix CHECK: Alignment should match open parenthesis in qlge_dbg.c, qlge_ethtool.c, qlge_main.c, and qlge_mpi.c. Also made changes to the following lines: WARNING: quoted string split across lines FILE: drivers/staging/qlge/qlge_main.c:81 WARNING: quoted string split across lines FILE: drivers/staging/qlge/qlge_main.c:87 WARNING: quoted string split across lines FILE: drivers/staging/qlge/qlge_main.c:3528 WARNING: quoted string split across lines FILE: drivers/staging/qlge/qlge_main.c:3536 CHECK: spaces preferred around that '*' (ctx:VxV) drivers/staging/qlge/qlge_main.c:4102 I made these changes due to touching these lines in the original fix Signed-off-by: Scott Schafer Link: https://lore.kernel.org/r/27ec7ee0a3ba8c1ad946077aacfcc6e40b98c106.1576086080.git.schaferjscott@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/qlge/qlge_dbg.c | 8 +- drivers/staging/qlge/qlge_ethtool.c | 34 +++-- drivers/staging/qlge/qlge_main.c | 184 +++++++++++++--------------- drivers/staging/qlge/qlge_mpi.c | 21 ++-- 4 files changed, 117 insertions(+), 130 deletions(-) diff --git a/drivers/staging/qlge/qlge_dbg.c b/drivers/staging/qlge/qlge_dbg.c index d56f2205effa..8cf39615c520 100644 --- a/drivers/staging/qlge/qlge_dbg.c +++ b/drivers/staging/qlge/qlge_dbg.c @@ -144,7 +144,8 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev, /* The XAUI needs to be read out per port */ status = ql_read_other_func_serdes_reg(qdev, - XG_SERDES_XAUI_HSS_PCS_START, &temp); + XG_SERDES_XAUI_HSS_PCS_START, + &temp); if (status) temp = XG_SERDES_ADDR_XAUI_PWR_DOWN; @@ -480,7 +481,8 @@ static int ql_get_mpi_shadow_regs(struct ql_adapter *qdev, u32 *buf) int status; for (i = 0; i < MPI_CORE_SH_REGS_CNT; i++, buf++) { - status = ql_write_mpi_reg(qdev, RISC_124, + status = ql_write_mpi_reg(qdev, + RISC_124, (SHADOW_OFFSET | i << SHADOW_REG_SHIFT)); if (status) goto end; @@ -1106,7 +1108,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) + sizeof(mpi_coredump->nic_routing_words), "Routing Words"); status = ql_get_routing_entries(qdev, - &mpi_coredump->nic_routing_words[0]); + &mpi_coredump->nic_routing_words[0]); if (status) goto err; diff --git a/drivers/staging/qlge/qlge_ethtool.c b/drivers/staging/qlge/qlge_ethtool.c index 3a4060f03e21..790997aff995 100644 --- a/drivers/staging/qlge/qlge_ethtool.c +++ b/drivers/staging/qlge/qlge_ethtool.c @@ -196,8 +196,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) */ cqicb = (struct cqicb *)&qdev->rx_ring[qdev->rss_ring_count]; if (le16_to_cpu(cqicb->irq_delay) != qdev->tx_coalesce_usecs || - le16_to_cpu(cqicb->pkt_delay) != - qdev->tx_max_coalesced_frames) { + le16_to_cpu(cqicb->pkt_delay) != qdev->tx_max_coalesced_frames) { for (i = qdev->rss_ring_count; i < qdev->rx_ring_count; i++) { rx_ring = &qdev->rx_ring[i]; cqicb = (struct cqicb *)rx_ring; @@ -206,7 +205,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) cpu_to_le16(qdev->tx_max_coalesced_frames); cqicb->flags = FLAGS_LI; status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb), - CFG_LCQ, rx_ring->cq_id); + CFG_LCQ, rx_ring->cq_id); if (status) { netif_err(qdev, ifup, qdev->ndev, "Failed to load CQICB.\n"); @@ -218,8 +217,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) /* Update the inbound (RSS) handler queues if they changed. */ cqicb = (struct cqicb *)&qdev->rx_ring[0]; if (le16_to_cpu(cqicb->irq_delay) != qdev->rx_coalesce_usecs || - le16_to_cpu(cqicb->pkt_delay) != - qdev->rx_max_coalesced_frames) { + le16_to_cpu(cqicb->pkt_delay) != qdev->rx_max_coalesced_frames) { for (i = 0; i < qdev->rss_ring_count; i++, rx_ring++) { rx_ring = &qdev->rx_ring[i]; cqicb = (struct cqicb *)rx_ring; @@ -228,7 +226,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) cpu_to_le16(qdev->rx_max_coalesced_frames); cqicb->flags = FLAGS_LI; status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb), - CFG_LCQ, rx_ring->cq_id); + CFG_LCQ, rx_ring->cq_id); if (status) { netif_err(qdev, ifup, qdev->ndev, "Failed to load CQICB.\n"); @@ -339,8 +337,8 @@ static void ql_get_strings(struct net_device *dev, u32 stringset, u8 *buf) case ETH_SS_STATS: for (index = 0; index < QLGE_STATS_LEN; index++) { memcpy(buf + index * ETH_GSTRING_LEN, - ql_gstrings_stats[index].stat_string, - ETH_GSTRING_LEN); + ql_gstrings_stats[index].stat_string, + ETH_GSTRING_LEN); } break; } @@ -432,7 +430,7 @@ static void ql_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) /* WOL is only supported for mezz card. */ if (ssys_dev == QLGE_MEZZ_SSYS_ID_068 || - ssys_dev == QLGE_MEZZ_SSYS_ID_180) { + ssys_dev == QLGE_MEZZ_SSYS_ID_180) { wol->supported = WAKE_MAGIC; wol->wolopts = qdev->wol; } @@ -445,9 +443,9 @@ static int ql_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) /* WOL is only supported for mezz card. */ if (ssys_dev != QLGE_MEZZ_SSYS_ID_068 && - ssys_dev != QLGE_MEZZ_SSYS_ID_180) { + ssys_dev != QLGE_MEZZ_SSYS_ID_180) { netif_info(qdev, drv, qdev->ndev, - "WOL is only supported for mezz card\n"); + "WOL is only supported for mezz card\n"); return -EOPNOTSUPP; } if (wol->wolopts & ~WAKE_MAGIC) @@ -507,7 +505,7 @@ static void ql_stop_loopback(struct ql_adapter *qdev) } static void ql_create_lb_frame(struct sk_buff *skb, - unsigned int frame_size) + unsigned int frame_size) { memset(skb->data, 0xFF, frame_size); frame_size &= ~1; @@ -517,13 +515,13 @@ static void ql_create_lb_frame(struct sk_buff *skb, } void ql_check_lb_frame(struct ql_adapter *qdev, - struct sk_buff *skb) + struct sk_buff *skb) { unsigned int frame_size = skb->len; if ((*(skb->data + 3) == 0xFF) && - (*(skb->data + frame_size / 2 + 10) == 0xBE) && - (*(skb->data + frame_size / 2 + 12) == 0xAF)) { + (*(skb->data + frame_size / 2 + 10) == 0xBE) && + (*(skb->data + frame_size / 2 + 12) == 0xAF)) { atomic_dec(&qdev->lb_count); return; } @@ -567,7 +565,7 @@ out: } static void ql_self_test(struct net_device *ndev, - struct ethtool_test *eth_test, u64 *data) + struct ethtool_test *eth_test, u64 *data) { struct ql_adapter *qdev = netdev_priv(ndev); @@ -673,7 +671,7 @@ static int ql_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *c) } static void ql_get_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) + struct ethtool_pauseparam *pause) { struct ql_adapter *qdev = netdev_priv(netdev); @@ -685,7 +683,7 @@ static void ql_get_pauseparam(struct net_device *netdev, } static int ql_set_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) + struct ethtool_pauseparam *pause) { struct ql_adapter *qdev = netdev_priv(netdev); int status = 0; diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c index b2f826822a51..0a0e50f8e26c 100644 --- a/drivers/staging/qlge/qlge_main.c +++ b/drivers/staging/qlge/qlge_main.c @@ -77,14 +77,12 @@ MODULE_PARM_DESC(qlge_irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy."); static int qlge_mpi_coredump; module_param(qlge_mpi_coredump, int, 0); MODULE_PARM_DESC(qlge_mpi_coredump, - "Option to enable MPI firmware dump. " - "Default is OFF - Do Not allocate memory. "); + "Option to enable MPI firmware dump. Default is OFF - Do Not allocate memory. "); static int qlge_force_coredump; module_param(qlge_force_coredump, int, 0); MODULE_PARM_DESC(qlge_force_coredump, - "Option to allow force of firmware core dump. " - "Default is OFF - Do not allow."); + "Option to allow force of firmware core dump. Default is OFF - Do not allow."); static const struct pci_device_id qlge_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)}, @@ -270,36 +268,34 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index, { status = ql_wait_reg_rdy(qdev, - MAC_ADDR_IDX, MAC_ADDR_MW, 0); + MAC_ADDR_IDX, MAC_ADDR_MW, 0); if (status) goto exit; ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ (index << MAC_ADDR_IDX_SHIFT) | /* index */ MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */ status = - ql_wait_reg_rdy(qdev, - MAC_ADDR_IDX, MAC_ADDR_MR, 0); + ql_wait_reg_rdy(qdev, MAC_ADDR_IDX, MAC_ADDR_MR, 0); if (status) goto exit; *value++ = ql_read32(qdev, MAC_ADDR_DATA); status = - ql_wait_reg_rdy(qdev, - MAC_ADDR_IDX, MAC_ADDR_MW, 0); + ql_wait_reg_rdy(qdev, MAC_ADDR_IDX, MAC_ADDR_MW, 0); if (status) goto exit; ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ (index << MAC_ADDR_IDX_SHIFT) | /* index */ MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */ status = - ql_wait_reg_rdy(qdev, - MAC_ADDR_IDX, MAC_ADDR_MR, 0); + ql_wait_reg_rdy(qdev, MAC_ADDR_IDX, MAC_ADDR_MR, 0); if (status) goto exit; *value++ = ql_read32(qdev, MAC_ADDR_DATA); if (type == MAC_ADDR_TYPE_CAM_MAC) { status = ql_wait_reg_rdy(qdev, - MAC_ADDR_IDX, MAC_ADDR_MW, 0); + MAC_ADDR_IDX, MAC_ADDR_MW, + 0); if (status) goto exit; ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ @@ -343,7 +339,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, status = ql_wait_reg_rdy(qdev, - MAC_ADDR_IDX, MAC_ADDR_MW, 0); + MAC_ADDR_IDX, MAC_ADDR_MW, 0); if (status) goto exit; ql_write32(qdev, MAC_ADDR_IDX, (offset++) | @@ -352,7 +348,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, ql_write32(qdev, MAC_ADDR_DATA, lower); status = ql_wait_reg_rdy(qdev, - MAC_ADDR_IDX, MAC_ADDR_MW, 0); + MAC_ADDR_IDX, MAC_ADDR_MW, 0); if (status) goto exit; ql_write32(qdev, MAC_ADDR_IDX, (offset++) | @@ -362,7 +358,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, ql_write32(qdev, MAC_ADDR_DATA, upper); status = ql_wait_reg_rdy(qdev, - MAC_ADDR_IDX, MAC_ADDR_MW, 0); + MAC_ADDR_IDX, MAC_ADDR_MW, 0); if (status) goto exit; break; @@ -375,8 +371,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | (addr[5]); status = - ql_wait_reg_rdy(qdev, - MAC_ADDR_IDX, MAC_ADDR_MW, 0); + ql_wait_reg_rdy(qdev, MAC_ADDR_IDX, MAC_ADDR_MW, 0); if (status) goto exit; ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ @@ -384,8 +379,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, type); /* type */ ql_write32(qdev, MAC_ADDR_DATA, lower); status = - ql_wait_reg_rdy(qdev, - MAC_ADDR_IDX, MAC_ADDR_MW, 0); + ql_wait_reg_rdy(qdev, MAC_ADDR_IDX, MAC_ADDR_MW, 0); if (status) goto exit; ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ @@ -393,8 +387,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, type); /* type */ ql_write32(qdev, MAC_ADDR_DATA, upper); status = - ql_wait_reg_rdy(qdev, - MAC_ADDR_IDX, MAC_ADDR_MW, 0); + ql_wait_reg_rdy(qdev, MAC_ADDR_IDX, MAC_ADDR_MW, 0); if (status) goto exit; ql_write32(qdev, MAC_ADDR_IDX, (offset) | /* offset */ @@ -423,8 +416,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, * That's bit-27 we're talking about. */ status = - ql_wait_reg_rdy(qdev, - MAC_ADDR_IDX, MAC_ADDR_MW, 0); + ql_wait_reg_rdy(qdev, MAC_ADDR_IDX, MAC_ADDR_MW, 0); if (status) goto exit; ql_write32(qdev, MAC_ADDR_IDX, offset | /* offset */ @@ -467,7 +459,8 @@ static int ql_set_mac_addr(struct ql_adapter *qdev, int set) if (status) return status; status = ql_set_mac_addr_reg(qdev, (u8 *) addr, - MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); + MAC_ADDR_TYPE_CAM_MAC, + qdev->func * MAX_CQ); ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); if (status) netif_err(qdev, ifup, qdev->ndev, @@ -672,14 +665,14 @@ static int ql_read_flash_word(struct ql_adapter *qdev, int offset, __le32 *data) int status = 0; /* wait for reg to come ready */ status = ql_wait_reg_rdy(qdev, - FLASH_ADDR, FLASH_ADDR_RDY, FLASH_ADDR_ERR); + FLASH_ADDR, FLASH_ADDR_RDY, FLASH_ADDR_ERR); if (status) goto exit; /* set up for reg read */ ql_write32(qdev, FLASH_ADDR, FLASH_ADDR_R | offset); /* wait for reg to come ready */ status = ql_wait_reg_rdy(qdev, - FLASH_ADDR, FLASH_ADDR_RDY, FLASH_ADDR_ERR); + FLASH_ADDR, FLASH_ADDR_RDY, FLASH_ADDR_ERR); if (status) goto exit; /* This data is stored on flash as an array of @@ -721,8 +714,9 @@ static int ql_get_8000_flash_params(struct ql_adapter *qdev) } status = ql_validate_flash(qdev, - sizeof(struct flash_params_8000) / sizeof(u16), - "8000"); + sizeof(struct flash_params_8000) / + sizeof(u16), + "8000"); if (status) { netif_err(qdev, ifup, qdev->ndev, "Invalid flash.\n"); status = -EINVAL; @@ -734,12 +728,12 @@ static int ql_get_8000_flash_params(struct ql_adapter *qdev) */ if (qdev->flash.flash_params_8000.data_type1 == 2) memcpy(mac_addr, - qdev->flash.flash_params_8000.mac_addr1, - qdev->ndev->addr_len); + qdev->flash.flash_params_8000.mac_addr1, + qdev->ndev->addr_len); else memcpy(mac_addr, - qdev->flash.flash_params_8000.mac_addr, - qdev->ndev->addr_len); + qdev->flash.flash_params_8000.mac_addr, + qdev->ndev->addr_len); if (!is_valid_ether_addr(mac_addr)) { netif_err(qdev, ifup, qdev->ndev, "Invalid MAC address.\n"); @@ -748,8 +742,8 @@ static int ql_get_8000_flash_params(struct ql_adapter *qdev) } memcpy(qdev->ndev->dev_addr, - mac_addr, - qdev->ndev->addr_len); + mac_addr, + qdev->ndev->addr_len); exit: ql_sem_unlock(qdev, SEM_FLASH_MASK); @@ -784,8 +778,9 @@ static int ql_get_8012_flash_params(struct ql_adapter *qdev) } status = ql_validate_flash(qdev, - sizeof(struct flash_params_8012) / sizeof(u16), - "8012"); + sizeof(struct flash_params_8012) / + sizeof(u16), + "8012"); if (status) { netif_err(qdev, ifup, qdev->ndev, "Invalid flash.\n"); status = -EINVAL; @@ -798,8 +793,8 @@ static int ql_get_8012_flash_params(struct ql_adapter *qdev) } memcpy(qdev->ndev->dev_addr, - qdev->flash.flash_params_8012.mac_addr, - qdev->ndev->addr_len); + qdev->flash.flash_params_8012.mac_addr, + qdev->ndev->addr_len); exit: ql_sem_unlock(qdev, SEM_FLASH_MASK); @@ -815,7 +810,7 @@ static int ql_write_xgmac_reg(struct ql_adapter *qdev, u32 reg, u32 data) int status; /* wait for reg to come ready */ status = ql_wait_reg_rdy(qdev, - XGMAC_ADDR, XGMAC_ADDR_RDY, XGMAC_ADDR_XME); + XGMAC_ADDR, XGMAC_ADDR_RDY, XGMAC_ADDR_XME); if (status) return status; /* write the data to the data reg */ @@ -834,14 +829,14 @@ int ql_read_xgmac_reg(struct ql_adapter *qdev, u32 reg, u32 *data) int status = 0; /* wait for reg to come ready */ status = ql_wait_reg_rdy(qdev, - XGMAC_ADDR, XGMAC_ADDR_RDY, XGMAC_ADDR_XME); + XGMAC_ADDR, XGMAC_ADDR_RDY, XGMAC_ADDR_XME); if (status) goto exit; /* set up for reg read */ ql_write32(qdev, XGMAC_ADDR, reg | XGMAC_ADDR_R); /* wait for reg to come ready */ status = ql_wait_reg_rdy(qdev, - XGMAC_ADDR, XGMAC_ADDR_RDY, XGMAC_ADDR_XME); + XGMAC_ADDR, XGMAC_ADDR_RDY, XGMAC_ADDR_XME); if (status) goto exit; /* get the data */ @@ -1436,10 +1431,9 @@ static void ql_update_mac_hdr_len(struct ql_adapter *qdev, /* Process an inbound completion from an rx ring. */ static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev, - struct rx_ring *rx_ring, - struct ib_mac_iocb_rsp *ib_mac_rsp, - u32 length, - u16 vlan_id) + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp, + u32 length, u16 vlan_id) { struct sk_buff *skb; struct qlge_bq_desc *lbq_desc = ql_get_curr_lchunk(qdev, rx_ring); @@ -1483,10 +1477,9 @@ static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev, /* Process an inbound completion from an rx ring. */ static void ql_process_mac_rx_page(struct ql_adapter *qdev, - struct rx_ring *rx_ring, - struct ib_mac_iocb_rsp *ib_mac_rsp, - u32 length, - u16 vlan_id) + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp, + u32 length, u16 vlan_id) { struct net_device *ndev = qdev->ndev; struct sk_buff *skb = NULL; @@ -1528,8 +1521,7 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", length); skb_fill_page_desc(skb, 0, lbq_desc->p.pg_chunk.page, - lbq_desc->p.pg_chunk.offset + hlen, - length - hlen); + lbq_desc->p.pg_chunk.offset + hlen, length - hlen); skb->len += length - hlen; skb->data_len += length - hlen; skb->truesize += length - hlen; @@ -1540,7 +1532,7 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, skb_checksum_none_assert(skb); if ((ndev->features & NETIF_F_RXCSUM) && - !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { + !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { /* TCP frame. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, @@ -1576,10 +1568,9 @@ err_out: /* Process an inbound completion from an rx ring. */ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, - struct rx_ring *rx_ring, - struct ib_mac_iocb_rsp *ib_mac_rsp, - u32 length, - u16 vlan_id) + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp, + u32 length, u16 vlan_id) { struct qlge_bq_desc *sbq_desc = qlge_get_curr_buf(&rx_ring->sbq); struct net_device *ndev = qdev->ndev; @@ -1648,7 +1639,7 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, * csum or frame errors. */ if ((ndev->features & NETIF_F_RXCSUM) && - !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { + !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { /* TCP frame. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, @@ -1779,8 +1770,7 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, "Chaining page at offset = %d, for %d bytes to skb.\n", lbq_desc->p.pg_chunk.offset, length); skb_fill_page_desc(skb, 0, lbq_desc->p.pg_chunk.page, - lbq_desc->p.pg_chunk.offset, - length); + lbq_desc->p.pg_chunk.offset, length); skb->len += length; skb->data_len += length; skb->truesize += length; @@ -1804,10 +1794,9 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", length); - skb_fill_page_desc(skb, 0, - lbq_desc->p.pg_chunk.page, - lbq_desc->p.pg_chunk.offset, - length); + skb_fill_page_desc(skb, 0, lbq_desc->p.pg_chunk.page, + lbq_desc->p.pg_chunk.offset, + length); skb->len += length; skb->data_len += length; skb->truesize += length; @@ -1857,9 +1846,8 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, "Adding page %d to skb for %d bytes.\n", i, size); skb_fill_page_desc(skb, i, - lbq_desc->p.pg_chunk.page, - lbq_desc->p.pg_chunk.offset, - size); + lbq_desc->p.pg_chunk.page, + lbq_desc->p.pg_chunk.offset, size); skb->len += size; skb->data_len += size; skb->truesize += size; @@ -1875,9 +1863,9 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, /* Process an inbound completion from an rx ring. */ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, - struct rx_ring *rx_ring, - struct ib_mac_iocb_rsp *ib_mac_rsp, - u16 vlan_id) + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp, + u16 vlan_id) { struct net_device *ndev = qdev->ndev; struct sk_buff *skb = NULL; @@ -1938,7 +1926,7 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, * csum or frame errors. */ if ((ndev->features & NETIF_F_RXCSUM) && - !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { + !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { /* TCP frame. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, @@ -1970,8 +1958,8 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, /* Process an inbound completion from an rx ring. */ static unsigned long ql_process_mac_rx_intr(struct ql_adapter *qdev, - struct rx_ring *rx_ring, - struct ib_mac_iocb_rsp *ib_mac_rsp) + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp) { u32 length = le32_to_cpu(ib_mac_rsp->data_len); u16 vlan_id = ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) && @@ -1986,34 +1974,34 @@ static unsigned long ql_process_mac_rx_intr(struct ql_adapter *qdev, * separate buffers. */ ql_process_mac_split_rx_intr(qdev, rx_ring, ib_mac_rsp, - vlan_id); + vlan_id); } else if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DS) { /* The data fit in a single small buffer. * Allocate a new skb, copy the data and * return the buffer to the free pool. */ - ql_process_mac_rx_skb(qdev, rx_ring, ib_mac_rsp, - length, vlan_id); + ql_process_mac_rx_skb(qdev, rx_ring, ib_mac_rsp, length, + vlan_id); } else if ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL) && !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK) && (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T)) { /* TCP packet in a page chunk that's been checksummed. * Tack it on to our GRO skb and let it go. */ - ql_process_mac_rx_gro_page(qdev, rx_ring, ib_mac_rsp, - length, vlan_id); + ql_process_mac_rx_gro_page(qdev, rx_ring, ib_mac_rsp, length, + vlan_id); } else if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL) { /* Non-TCP packet in a page chunk. Allocate an * skb, tack it on frags, and send it up. */ - ql_process_mac_rx_page(qdev, rx_ring, ib_mac_rsp, - length, vlan_id); + ql_process_mac_rx_page(qdev, rx_ring, ib_mac_rsp, length, + vlan_id); } else { /* Non-TCP/UDP large frames that span multiple buffers * can be processed corrrectly by the split frame logic. */ ql_process_mac_split_rx_intr(qdev, rx_ring, ib_mac_rsp, - vlan_id); + vlan_id); } return (unsigned long)length; @@ -2230,8 +2218,8 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget) * it's not empty then service it. */ if ((ctx->irq_mask & (1 << trx_ring->cq_id)) && - (ql_read_sh_reg(trx_ring->prod_idx_sh_reg) != - trx_ring->cnsmr_idx)) { + (ql_read_sh_reg(trx_ring->prod_idx_sh_reg) != + trx_ring->cnsmr_idx)) { netif_printk(qdev, intr, KERN_DEBUG, qdev->ndev, "%s: Servicing TX completion ring %d.\n", __func__, trx_ring->cq_id); @@ -2305,7 +2293,7 @@ static int qlge_update_hw_vlan_features(struct net_device *ndev, } static int qlge_set_features(struct net_device *ndev, - netdev_features_t features) + netdev_features_t features) { netdev_features_t changed = ndev->features ^ features; int err; @@ -2448,7 +2436,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) * Check MPI processor activity. */ if ((var & STS_PI) && - (ql_read32(qdev, INTR_MASK) & INTR_MASK_PI)) { + (ql_read32(qdev, INTR_MASK) & INTR_MASK_PI)) { /* * We've got an async event or mailbox completion. * Handle it and clear the source of the interrupt. @@ -2457,7 +2445,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) "Got MPI processor interrupt.\n"); ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); queue_delayed_work_on(smp_processor_id(), - qdev->workqueue, &qdev->mpi_work, 0); + qdev->workqueue, &qdev->mpi_work, 0); work_done++; } @@ -3531,19 +3519,17 @@ static int ql_route_initialize(struct ql_adapter *qdev) return status; status = ql_set_routing_reg(qdev, RT_IDX_IP_CSUM_ERR_SLOT, - RT_IDX_IP_CSUM_ERR, 1); + RT_IDX_IP_CSUM_ERR, 1); if (status) { netif_err(qdev, ifup, qdev->ndev, - "Failed to init routing register " - "for IP CSUM error packets.\n"); + "Failed to init routing register for IP CSUM error packets.\n"); goto exit; } status = ql_set_routing_reg(qdev, RT_IDX_TCP_UDP_CSUM_ERR_SLOT, - RT_IDX_TU_CSUM_ERR, 1); + RT_IDX_TU_CSUM_ERR, 1); if (status) { netif_err(qdev, ifup, qdev->ndev, - "Failed to init routing register " - "for TCP/UDP CSUM error packets.\n"); + "Failed to init routing register for TCP/UDP CSUM error packets.\n"); goto exit; } status = ql_set_routing_reg(qdev, RT_IDX_BCAST_SLOT, RT_IDX_BCAST, 1); @@ -3557,7 +3543,7 @@ static int ql_route_initialize(struct ql_adapter *qdev) */ if (qdev->rss_ring_count > 1) { status = ql_set_routing_reg(qdev, RT_IDX_RSS_MATCH_SLOT, - RT_IDX_RSS_MATCH, 1); + RT_IDX_RSS_MATCH, 1); if (status) { netif_err(qdev, ifup, qdev->ndev, "Failed to init routing register for MATCH RSS packets.\n"); @@ -3655,7 +3641,7 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) /* Default WOL is enable on Mezz cards */ if (qdev->pdev->subsystem_device == 0x0068 || - qdev->pdev->subsystem_device == 0x0180) + qdev->pdev->subsystem_device == 0x0180) qdev->wol = WAKE_MAGIC; /* Start up the rx queues. */ @@ -3882,7 +3868,7 @@ static int ql_adapter_up(struct ql_adapter *qdev) * link is up the turn on the carrier. */ if ((ql_read32(qdev, STS) & qdev->port_init) && - (ql_read32(qdev, STS) & qdev->port_link_up)) + (ql_read32(qdev, STS) & qdev->port_link_up)) ql_link_on(qdev); /* Restore rx mode. */ clear_bit(QL_ALLMULTI, &qdev->flags); @@ -4109,7 +4095,7 @@ static int qlge_change_mtu(struct net_device *ndev, int new_mtu) return -EINVAL; queue_delayed_work(qdev->workqueue, - &qdev->mpi_port_cfg_work, 3*HZ); + &qdev->mpi_port_cfg_work, 3 * HZ); ndev->mtu = new_mtu; @@ -4268,7 +4254,8 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p) if (status) return status; status = ql_set_mac_addr_reg(qdev, (u8 *) ndev->dev_addr, - MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); + MAC_ADDR_TYPE_CAM_MAC, + qdev->func * MAX_CQ); if (status) netif_err(qdev, hw, qdev->ndev, "Failed to load MAC address.\n"); ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); @@ -4335,7 +4322,7 @@ static int ql_get_alt_pcie_func(struct ql_adapter *qdev) u32 nic_func1, nic_func2; status = ql_read_mpi_reg(qdev, MPI_TEST_FUNC_PORT_CFG, - &temp); + &temp); if (status) return status; @@ -4583,7 +4570,8 @@ static int qlge_probe(struct pci_dev *pdev, int err = 0; ndev = alloc_etherdev_mq(sizeof(struct ql_adapter), - min(MAX_CPUS, netif_get_num_default_rss_queues())); + min(MAX_CPUS, + netif_get_num_default_rss_queues())); if (!ndev) return -ENOMEM; diff --git a/drivers/staging/qlge/qlge_mpi.c b/drivers/staging/qlge/qlge_mpi.c index 843b32240a73..bb03b2fa7233 100644 --- a/drivers/staging/qlge/qlge_mpi.c +++ b/drivers/staging/qlge/qlge_mpi.c @@ -134,7 +134,7 @@ static int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp) for (i = 0; i < mbcp->out_count; i++) { status = ql_read_mpi_reg(qdev, qdev->mailbox_out + i, - &mbcp->mbox_out[i]); + &mbcp->mbox_out[i]); if (status) { netif_err(qdev, drv, qdev->ndev, "Failed mailbox read.\n"); break; @@ -184,7 +184,7 @@ static int ql_exec_mb_cmd(struct ql_adapter *qdev, struct mbox_params *mbcp) */ for (i = 0; i < mbcp->in_count; i++) { status = ql_write_mpi_reg(qdev, qdev->mailbox_in + i, - mbcp->mbox_in[i]); + mbcp->mbox_in[i]); if (status) goto end; } @@ -293,7 +293,7 @@ static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) */ ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); queue_delayed_work(qdev->workqueue, - &qdev->mpi_port_cfg_work, 0); + &qdev->mpi_port_cfg_work, 0); } ql_link_on(qdev); @@ -745,7 +745,7 @@ int ql_mb_set_port_cfg(struct ql_adapter *qdev) } static int ql_mb_dump_ram(struct ql_adapter *qdev, u64 req_dma, u32 addr, - u32 size) + u32 size) { int status = 0; struct mbox_params mbc; @@ -779,14 +779,14 @@ static int ql_mb_dump_ram(struct ql_adapter *qdev, u64 req_dma, u32 addr, /* Issue a mailbox command to dump RISC RAM. */ int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, - u32 ram_addr, int word_count) + u32 ram_addr, int word_count) { int status; char *my_buf; dma_addr_t buf_dma; my_buf = pci_alloc_consistent(qdev->pdev, word_count * sizeof(u32), - &buf_dma); + &buf_dma); if (!my_buf) return -EIO; @@ -795,7 +795,7 @@ int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, memcpy(buf, my_buf, word_count * sizeof(u32)); pci_free_consistent(qdev->pdev, word_count * sizeof(u32), my_buf, - buf_dma); + buf_dma); return status; } @@ -918,7 +918,7 @@ static int ql_idc_wait(struct ql_adapter *qdev) */ wait_time = wait_for_completion_timeout(&qdev->ide_completion, - wait_time); + wait_time); if (!wait_time) { netif_err(qdev, drv, qdev->ndev, "IDC Timeout.\n"); break; @@ -1125,8 +1125,7 @@ void ql_mpi_port_cfg_work(struct work_struct *work) } if (qdev->link_config & CFG_JUMBO_FRAME_SIZE && - qdev->max_frame_size == - CFG_DEFAULT_MAX_FRAME_SIZE) + qdev->max_frame_size == CFG_DEFAULT_MAX_FRAME_SIZE) goto end; qdev->link_config |= CFG_JUMBO_FRAME_SIZE; @@ -1273,7 +1272,7 @@ void ql_mpi_reset_work(struct work_struct *work) netif_err(qdev, drv, qdev->ndev, "Core is dumped!\n"); qdev->core_is_dumped = 1; queue_delayed_work(qdev->workqueue, - &qdev->mpi_core_to_log, 5 * HZ); + &qdev->mpi_core_to_log, 5 * HZ); } ql_soft_reset_mpi_risc(qdev); } From c1d3fb8abe667cd9aa59f3a176ca4d0636d9b44b Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Fri, 13 Dec 2019 13:04:14 +0100 Subject: [PATCH 093/353] staging: most: rename core.h to most.h This patch renames the core header file core.h to most.h. The intention behind this is to have a meaningful name once this file is moved to the /include/linux directory. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1576238662-16512-2-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 2 +- drivers/staging/most/configfs.c | 2 +- drivers/staging/most/core.c | 2 +- drivers/staging/most/dim2/dim2.c | 2 +- drivers/staging/most/i2c/i2c.c | 2 +- drivers/staging/most/{core.h => most.h} | 0 drivers/staging/most/net/net.c | 2 +- drivers/staging/most/sound/sound.c | 2 +- drivers/staging/most/usb/usb.c | 2 +- drivers/staging/most/video/video.c | 2 +- 10 files changed, 9 insertions(+), 9 deletions(-) rename drivers/staging/most/{core.h => most.h} (100%) diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index f880147c82fd..df4cb5a3818e 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -16,7 +16,7 @@ #include #include #include -#include "most/core.h" +#include "most/most.h" #define CHRDEV_REGION_SIZE 50 diff --git a/drivers/staging/most/configfs.c b/drivers/staging/most/configfs.c index 34a9fb53985c..e17d8461a916 100644 --- a/drivers/staging/most/configfs.c +++ b/drivers/staging/most/configfs.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include struct mdev_link { struct config_item item; diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 51a6b41d5b82..e32030c38255 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #define MAX_CHANNELS 64 #define STRING_SIZE 80 diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index 64c979155a49..e15e847ef58e 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -21,7 +21,7 @@ #include #include -#include "most/core.h" +#include "most/most.h" #include "hal.h" #include "errors.h" #include "sysfs.h" diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c index 4a4fc1005932..d4606acba942 100644 --- a/drivers/staging/most/i2c/i2c.c +++ b/drivers/staging/most/i2c/i2c.c @@ -14,7 +14,7 @@ #include #include -#include "most/core.h" +#include "most/most.h" enum { CH_RX, CH_TX, NUM_CHANNELS }; diff --git a/drivers/staging/most/core.h b/drivers/staging/most/most.h similarity index 100% rename from drivers/staging/most/core.h rename to drivers/staging/most/most.h diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index 6cab1bb8956e..34d93c47a70b 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -15,7 +15,7 @@ #include #include #include -#include "most/core.h" +#include "most/most.h" #define MEP_HDR_LEN 8 #define MDP_HDR_LEN 16 diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 1ccfcb8f78b9..38642b2be306 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #define DRIVER_NAME "sound" #define STRING_SIZE 80 diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c index 360cb5b7a10b..69756ca719d8 100644 --- a/drivers/staging/most/usb/usb.c +++ b/drivers/staging/most/usb/usb.c @@ -23,7 +23,7 @@ #include #include #include -#include "most/core.h" +#include "most/most.h" #define USB_MTU 512 #define NO_ISOCHRONOUS_URB 0 diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index 10c1ef7e3a3e..b75ccc86e178 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -21,7 +21,7 @@ #include #include -#include "most/core.h" +#include "most/most.h" #define V4L2_CMP_MAX_INPUT 1 From 45917e79202c7a0b67f1331c154afba77a3d4a1e Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Fri, 13 Dec 2019 13:04:15 +0100 Subject: [PATCH 094/353] staging: most: rename struct core_component The stuctures defined in the most.h header file will be exposed to the kernel once the file is moved out of the staging area. That's why the name is changed into something more descriptive. Reported-by: Greg Kroah-Hartman Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1576238662-16512-3-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 2 +- drivers/staging/most/configfs.c | 4 ++-- drivers/staging/most/core.c | 32 +++++++++++++++--------------- drivers/staging/most/most.h | 20 +++++++++---------- drivers/staging/most/net/net.c | 4 ++-- drivers/staging/most/sound/sound.c | 6 +++--- drivers/staging/most/video/video.c | 4 ++-- 7 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index df4cb5a3818e..9ce2f23dcaed 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -25,7 +25,7 @@ static struct cdev_component { struct ida minor_id; unsigned int major; struct class *class; - struct core_component cc; + struct most_component cc; } comp; struct comp_channel { diff --git a/drivers/staging/most/configfs.c b/drivers/staging/most/configfs.c index e17d8461a916..d67102229afe 100644 --- a/drivers/staging/most/configfs.c +++ b/drivers/staging/most/configfs.c @@ -630,7 +630,7 @@ static struct most_sound most_sound_subsys = { }, }; -int most_register_configfs_subsys(struct core_component *c) +int most_register_configfs_subsys(struct most_component *c) { int ret; @@ -674,7 +674,7 @@ void most_interface_register_notify(const char *mdev) most_cfg_complete("sound"); } -void most_deregister_configfs_subsys(struct core_component *c) +void most_deregister_configfs_subsys(struct most_component *c) { if (!strcmp(c->name, "cdev")) configfs_unregister_subsystem(&most_cdev.subsys); diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index e32030c38255..af542ed6c7f0 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -39,7 +39,7 @@ static struct mostcore { #define to_driver(d) container_of(d, struct mostcore, drv) struct pipe { - struct core_component *comp; + struct most_component *comp; int refs; int num_buffers; }; @@ -454,9 +454,9 @@ static const struct attribute_group *interface_attr_groups[] = { NULL, }; -static struct core_component *match_component(char *name) +static struct most_component *match_component(char *name) { - struct core_component *comp; + struct most_component *comp; list_for_each_entry(comp, &mc.comp_list, list) { if (!strcmp(comp->name, name)) @@ -510,7 +510,7 @@ static ssize_t links_show(struct device_driver *drv, char *buf) static ssize_t components_show(struct device_driver *drv, char *buf) { - struct core_component *comp; + struct most_component *comp; int offs = 0; list_for_each_entry(comp, &mc.comp_list, list) { @@ -544,12 +544,12 @@ static struct most_channel *get_channel(char *mdev, char *mdev_ch) static inline int link_channel_to_component(struct most_channel *c, - struct core_component *comp, + struct most_component *comp, char *name, char *comp_param) { int ret; - struct core_component **comp_ptr; + struct most_component **comp_ptr; if (!c->pipe0.comp) comp_ptr = &c->pipe0.comp; @@ -660,7 +660,7 @@ int most_set_cfg_packets_xact(char *mdev, char *mdev_ch, u16 val) int most_cfg_complete(char *comp_name) { - struct core_component *comp; + struct most_component *comp; comp = match_component(comp_name); if (!comp) @@ -673,7 +673,7 @@ int most_add_link(char *mdev, char *mdev_ch, char *comp_name, char *link_name, char *comp_param) { struct most_channel *c = get_channel(mdev, mdev_ch); - struct core_component *comp = match_component(comp_name); + struct most_component *comp = match_component(comp_name); if (!c || !comp) return -ENODEV; @@ -684,7 +684,7 @@ int most_add_link(char *mdev, char *mdev_ch, char *comp_name, char *link_name, int most_remove_link(char *mdev, char *mdev_ch, char *comp_name) { struct most_channel *c; - struct core_component *comp; + struct most_component *comp; comp = match_component(comp_name); if (!comp) @@ -950,7 +950,7 @@ static void most_write_completion(struct mbo *mbo) } int channel_has_mbo(struct most_interface *iface, int id, - struct core_component *comp) + struct most_component *comp) { struct most_channel *c = iface->p->channel[id]; unsigned long flags; @@ -981,7 +981,7 @@ EXPORT_SYMBOL_GPL(channel_has_mbo); * Returns a pointer to MBO on success or NULL otherwise. */ struct mbo *most_get_mbo(struct most_interface *iface, int id, - struct core_component *comp) + struct most_component *comp) { struct mbo *mbo; struct most_channel *c; @@ -1087,7 +1087,7 @@ static void most_read_completion(struct mbo *mbo) * Returns 0 on success or error code otherwise. */ int most_start_channel(struct most_interface *iface, int id, - struct core_component *comp) + struct most_component *comp) { int num_buffer; int ret; @@ -1157,7 +1157,7 @@ EXPORT_SYMBOL_GPL(most_start_channel); * @comp: driver component */ int most_stop_channel(struct most_interface *iface, int id, - struct core_component *comp) + struct most_component *comp) { struct most_channel *c; @@ -1215,7 +1215,7 @@ EXPORT_SYMBOL_GPL(most_stop_channel); * most_register_component - registers a driver component with the core * @comp: driver component */ -int most_register_component(struct core_component *comp) +int most_register_component(struct most_component *comp) { if (!comp) { pr_err("Bad component\n"); @@ -1231,7 +1231,7 @@ static int disconnect_channels(struct device *dev, void *data) { struct most_interface *iface; struct most_channel *c, *tmp; - struct core_component *comp = data; + struct most_component *comp = data; iface = to_most_interface(dev); list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { @@ -1249,7 +1249,7 @@ static int disconnect_channels(struct device *dev, void *data) * most_deregister_component - deregisters a driver component with the core * @comp: driver component */ -int most_deregister_component(struct core_component *comp) +int most_deregister_component(struct most_component *comp) { if (!comp) { pr_err("Bad component\n"); diff --git a/drivers/staging/most/most.h b/drivers/staging/most/most.h index 1380e7586376..fa6b29fb32f7 100644 --- a/drivers/staging/most/most.h +++ b/drivers/staging/most/most.h @@ -254,7 +254,7 @@ struct most_interface { #define to_most_interface(d) container_of(d, struct most_interface, dev) /** - * struct core_component - identifies a loadable component for the mostcore + * struct most_component - identifies a loadable component for the mostcore * @list: list_head * @name: component name * @probe_channel: function for core to notify driver about channel connection @@ -262,7 +262,7 @@ struct most_interface { * @rx_completion: completion handler for received packets * @tx_completion: completion handler for transmitted packets */ -struct core_component { +struct most_component { struct list_head list; const char *name; struct module *mod; @@ -310,20 +310,20 @@ void most_stop_enqueue(struct most_interface *iface, int channel_idx); * in wait fifo. */ void most_resume_enqueue(struct most_interface *iface, int channel_idx); -int most_register_component(struct core_component *comp); -int most_deregister_component(struct core_component *comp); +int most_register_component(struct most_component *comp); +int most_deregister_component(struct most_component *comp); struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx, - struct core_component *comp); + struct most_component *comp); void most_put_mbo(struct mbo *mbo); int channel_has_mbo(struct most_interface *iface, int channel_idx, - struct core_component *comp); + struct most_component *comp); int most_start_channel(struct most_interface *iface, int channel_idx, - struct core_component *comp); + struct most_component *comp); int most_stop_channel(struct most_interface *iface, int channel_idx, - struct core_component *comp); + struct most_component *comp); int __init configfs_init(void); -int most_register_configfs_subsys(struct core_component *comp); -void most_deregister_configfs_subsys(struct core_component *comp); +int most_register_configfs_subsys(struct most_component *comp); +void most_deregister_configfs_subsys(struct most_component *comp); int most_add_link(char *mdev, char *mdev_ch, char *comp_name, char *link_name, char *comp_param); int most_remove_link(char *mdev, char *mdev_ch, char *comp_name); diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index 34d93c47a70b..e3dd33701a15 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -70,7 +70,7 @@ struct net_dev_context { static struct list_head net_devices = LIST_HEAD_INIT(net_devices); static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */ static DEFINE_SPINLOCK(list_lock); /* list_head, ch->linked = false, dev_hold */ -static struct core_component comp; +static struct most_component comp; static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) { @@ -497,7 +497,7 @@ put_nd: return ret; } -static struct core_component comp = { +static struct most_component comp = { .mod = THIS_MODULE, .name = "net", .probe_channel = comp_probe_channel, diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 38642b2be306..23baf4bd7c12 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -22,7 +22,7 @@ #define DRIVER_NAME "sound" #define STRING_SIZE 80 -static struct core_component comp; +static struct most_component comp; /** * struct channel - private structure to keep channel specific data @@ -736,9 +736,9 @@ static int audio_tx_completion(struct most_interface *iface, int channel_id) } /** - * Initialization of the struct core_component + * Initialization of the struct most_component */ -static struct core_component comp = { +static struct most_component comp = { .mod = THIS_MODULE, .name = DRIVER_NAME, .probe_channel = audio_probe_channel, diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index b75ccc86e178..0f45b042486c 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -25,7 +25,7 @@ #define V4L2_CMP_MAX_INPUT 1 -static struct core_component comp; +static struct most_component comp; struct most_video_dev { struct most_interface *iface; @@ -527,7 +527,7 @@ static int comp_disconnect_channel(struct most_interface *iface, return 0; } -static struct core_component comp = { +static struct most_component comp = { .mod = THIS_MODULE, .name = "video", .probe_channel = comp_probe_channel, From b4e37a5e2c3202438f777410481a55de7137d0d4 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Fri, 13 Dec 2019 13:04:16 +0100 Subject: [PATCH 095/353] staging: most: rename enum mbo_status_flags The data structures of the most.h header file will be exposed to the kernel once the file is moved out of the staging area. This is why the name is prefixed with the string 'most'. Reported-by: Greg Kroah-Hartman Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1576238662-16512-4-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/most.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/most/most.h b/drivers/staging/most/most.h index fa6b29fb32f7..d93c6cea3a17 100644 --- a/drivers/staging/most/most.h +++ b/drivers/staging/most/most.h @@ -47,7 +47,7 @@ enum most_channel_data_type { MOST_CH_SYNC = 1 << 5, }; -enum mbo_status_flags { +enum most_status_flags { /* MBO was processed successfully (data was send or received )*/ MBO_SUCCESS = 0, /* The MBO contains wrong or missing information. */ @@ -184,7 +184,7 @@ struct mbo { dma_addr_t bus_address; u16 buffer_length; u16 processed_length; - enum mbo_status_flags status; + enum most_status_flags status; void (*complete)(struct mbo *mbo); }; From d72f82635e3317b5e035af40aa815c6d064c2fee Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Fri, 13 Dec 2019 13:04:17 +0100 Subject: [PATCH 096/353] staging: most: configfs: use strlcpy This patch uses strlcpy to copy data provided by userspace in order to not overflow the allocated space. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1576238662-16512-5-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/configfs.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/most/configfs.c b/drivers/staging/most/configfs.c index d67102229afe..9fbcadfafba2 100644 --- a/drivers/staging/most/configfs.c +++ b/drivers/staging/most/configfs.c @@ -197,7 +197,7 @@ static ssize_t mdev_link_device_store(struct config_item *item, { struct mdev_link *mdev_link = to_mdev_link(item); - strcpy(mdev_link->device, page); + strlcpy(mdev_link->device, page, sizeof(mdev_link->device)); strim(mdev_link->device); return count; } @@ -212,7 +212,7 @@ static ssize_t mdev_link_channel_store(struct config_item *item, { struct mdev_link *mdev_link = to_mdev_link(item); - strcpy(mdev_link->channel, page); + strlcpy(mdev_link->channel, page, sizeof(mdev_link->channel)); strim(mdev_link->channel); return count; } @@ -227,7 +227,8 @@ static ssize_t mdev_link_comp_store(struct config_item *item, { struct mdev_link *mdev_link = to_mdev_link(item); - strcpy(mdev_link->comp, page); + strlcpy(mdev_link->comp, page, sizeof(mdev_link->comp)); + strim(mdev_link->comp); return count; } @@ -242,7 +243,8 @@ static ssize_t mdev_link_comp_params_store(struct config_item *item, { struct mdev_link *mdev_link = to_mdev_link(item); - strcpy(mdev_link->comp_params, page); + strlcpy(mdev_link->comp_params, page, sizeof(mdev_link->comp_params)); + strim(mdev_link->comp_params); return count; } From c3bb9d883f1a5b2e60675779205e7c6ded2272aa Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Fri, 13 Dec 2019 13:04:18 +0100 Subject: [PATCH 097/353] staging: most: configfs: reduce array size This patch reduces the size of the arrays inside the mdev_link struct to a reasonable value. Reported-by: Joe Perches Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1576238662-16512-6-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/configfs.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/staging/most/configfs.c b/drivers/staging/most/configfs.c index 9fbcadfafba2..9818f6c8b22a 100644 --- a/drivers/staging/most/configfs.c +++ b/drivers/staging/most/configfs.c @@ -12,6 +12,8 @@ #include #include +#define MAX_STRING_SIZE 80 + struct mdev_link { struct config_item item; struct list_head list; @@ -22,13 +24,13 @@ struct mdev_link { u16 subbuffer_size; u16 packets_per_xact; u16 dbr_size; - char datatype[PAGE_SIZE]; - char direction[PAGE_SIZE]; - char name[PAGE_SIZE]; - char device[PAGE_SIZE]; - char channel[PAGE_SIZE]; - char comp[PAGE_SIZE]; - char comp_params[PAGE_SIZE]; + char datatype[MAX_STRING_SIZE]; + char direction[MAX_STRING_SIZE]; + char name[MAX_STRING_SIZE]; + char device[MAX_STRING_SIZE]; + char channel[MAX_STRING_SIZE]; + char comp[MAX_STRING_SIZE]; + char comp_params[MAX_STRING_SIZE]; }; static struct list_head mdev_link_list; From 6f4d22d76baa73c5bc99d669d68c862b60a04a3d Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Fri, 13 Dec 2019 13:04:19 +0100 Subject: [PATCH 098/353] staging: most: use angle brackets in include path This patch replaces the double quotes in all include paths with angle brackets. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1576238662-16512-7-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 2 +- drivers/staging/most/dim2/dim2.c | 2 +- drivers/staging/most/i2c/i2c.c | 2 +- drivers/staging/most/net/net.c | 2 +- drivers/staging/most/usb/usb.c | 2 +- drivers/staging/most/video/video.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index 9ce2f23dcaed..59f346d1f4af 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -16,7 +16,7 @@ #include #include #include -#include "most/most.h" +#include #define CHRDEV_REGION_SIZE 50 diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index e15e847ef58e..9eb10fc0903e 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -21,7 +21,7 @@ #include #include -#include "most/most.h" +#include #include "hal.h" #include "errors.h" #include "sysfs.h" diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c index d4606acba942..d07719c38fc9 100644 --- a/drivers/staging/most/i2c/i2c.c +++ b/drivers/staging/most/i2c/i2c.c @@ -14,7 +14,7 @@ #include #include -#include "most/most.h" +#include enum { CH_RX, CH_TX, NUM_CHANNELS }; diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index e3dd33701a15..db4273256ce8 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -15,7 +15,7 @@ #include #include #include -#include "most/most.h" +#include #define MEP_HDR_LEN 8 #define MDP_HDR_LEN 16 diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c index 69756ca719d8..491b38e91e9d 100644 --- a/drivers/staging/most/usb/usb.c +++ b/drivers/staging/most/usb/usb.c @@ -23,7 +23,7 @@ #include #include #include -#include "most/most.h" +#include #define USB_MTU 512 #define NO_ISOCHRONOUS_URB 0 diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index 0f45b042486c..9e9e45ac386e 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -21,7 +21,7 @@ #include #include -#include "most/most.h" +#include #define V4L2_CMP_MAX_INPUT 1 From dc497b4b0cd460de63413003cc64aa44cc2137e0 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 14 Dec 2019 11:09:54 +0100 Subject: [PATCH 099/353] staging: rtl8188eu: cleanup comparsions to NULL in rtw_mlme_ext.c Cleanup comparsions to NULL reported by checkpatch. if (x == NULL) -> if (!x) if (x != NULL) -> if (x) Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20191214100955.16670-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index e984b4605e91..e122ef165085 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -751,7 +751,7 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) + if (!pmgntframe) return; /* update attribute */ @@ -980,7 +980,7 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, break; } - if ((pbuf == NULL) || (ie_len == 0)) + if (!pbuf || ie_len == 0) break; } } @@ -1120,7 +1120,7 @@ static void issue_assocreq(struct adapter *padapter) /* HT caps */ if (padapter->mlmepriv.htpriv.ht_option) { p = rtw_get_ie((pmlmeinfo->network.ies + sizeof(struct ndis_802_11_fixed_ie)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.ie_length - sizeof(struct ndis_802_11_fixed_ie))); - if ((p != NULL) && (!(is_ap_in_tkip(padapter)))) { + if (p && !is_ap_in_tkip(padapter)) { memcpy(&pmlmeinfo->HT_caps, p + 2, sizeof(struct ieee80211_ht_cap)); /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */ @@ -1263,7 +1263,7 @@ int issue_nulldata(struct adapter *padapter, unsigned char *da, struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; /* da == NULL, assume it's null data for sta to ap*/ - if (da == NULL) + if (!da) da = pnetwork->MacAddress; do { @@ -1392,7 +1392,7 @@ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network; /* da == NULL, assume it's null data for sta to ap*/ - if (da == NULL) + if (!da) da = pnetwork->MacAddress; do { @@ -1444,7 +1444,7 @@ static int _issue_deauth(struct adapter *padapter, unsigned char *da, __le16 le_tmp; pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) + if (!pmgntframe) goto exit; /* update attribute */ @@ -1780,7 +1780,7 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) pbss_network = (struct wlan_bssid_ex *)&pnetwork->network; p = rtw_get_ie(pbss_network->ies + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->ie_length - _FIXED_IE_LENGTH_); - if ((p == NULL) || (len == 0)) { /* non-HT */ + if (!p || len == 0) { /* non-HT */ if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14)) continue; @@ -1833,7 +1833,7 @@ unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr) return _SUCCESS; psta = rtw_get_stainfo(pstapriv, addr); - if (psta == NULL) + if (!psta) return _SUCCESS; if (initiator == 0) { /* recipient */ @@ -2082,7 +2082,7 @@ static u8 collect_bss_info(struct adapter *padapter, /* checking rate info... */ i = 0; p = rtw_get_ie(bssid->ies + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->ie_length - ie_offset); - if (p != NULL) { + if (p) { if (len > NDIS_802_11_LENGTH_RATES_EX) { DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len); return _FAIL; @@ -2596,7 +2596,7 @@ static unsigned int OnBeacon(struct adapter *padapter, if (((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) { psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); - if (psta != NULL) { + if (psta) { ret = rtw_check_bcn_info(padapter, pframe, len); if (!ret) { DBG_88E_LEVEL(_drv_info_, "ap has changed, disconnect now\n "); @@ -2610,7 +2610,7 @@ static unsigned int OnBeacon(struct adapter *padapter, } } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); - if (psta != NULL) { + if (psta) { /* update WMM, ERP in the beacon */ /* todo: the timer is used instead of the number of the beacon received */ if ((sta_rx_pkts(psta) & 0xf) == 0) @@ -2761,7 +2761,7 @@ static unsigned int OnAuth(struct adapter *padapter, p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, &ie_len, len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); - if ((p == NULL) || (ie_len <= 0)) { + if (!p || ie_len <= 0) { DBG_88E("auth rejected because challenge failure!(1)\n"); status = _STATS_CHALLENGE_FAIL_; goto auth_fail; @@ -2855,7 +2855,7 @@ static unsigned int OnAuthClient(struct adapter *padapter, p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, &len, pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_); - if (p == NULL) + if (!p) goto authclnt_fail; memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len); @@ -2987,7 +2987,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, /* check if the supported rate is ok */ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); - if (p == NULL) { + if (!p) { DBG_88E("Rx a sta assoc-req which supported rate is empty!\n"); /* use our own rate set as statoin used */ /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */ @@ -3001,7 +3001,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); - if (p != NULL) { + if (p) { if (supportRateNum <= sizeof(supportRate)) { memcpy(supportRate+supportRateNum, p+2, ie_len); supportRateNum += ie_len; @@ -3146,7 +3146,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0; for (;;) { p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); - if (p != NULL) { + if (p) { if (!memcmp(p+2, WMM_IE, 6)) { pstat->flags |= WLAN_STA_WME; @@ -3245,7 +3245,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, DBG_88E(" old AID %d\n", pstat->aid); } else { for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) - if (pstapriv->sta_aid[pstat->aid - 1] == NULL) + if (!pstapriv->sta_aid[pstat->aid - 1]) break; /* if (pstat->aid > NUM_STA) { */ @@ -3958,7 +3958,7 @@ static void init_channel_list(struct adapter *padapter, ((o->bw == BW40MINUS) || (o->bw == BW40PLUS))) continue; - if (reg == NULL) { + if (!reg) { reg = &channel_list->reg_class[cla]; cla++; reg->reg_class = o->op_class; @@ -5333,7 +5333,7 @@ u8 set_tx_beacon_cmd(struct adapter *padapter) ptxBeacon_parm = kmemdup(&pmlmeinfo->network, sizeof(struct wlan_bssid_ex), GFP_ATOMIC); - if (ptxBeacon_parm == NULL) { + if (!ptxBeacon_parm) { kfree(ph2c); res = _FAIL; goto exit; From 92ee2034696cd7fcbfe8539eb93aefb0459bd931 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 14 Dec 2019 11:09:55 +0100 Subject: [PATCH 100/353] staging: rtl8188eu: add spaces around operators in rtw_mlme_ext.c Add missing spaces around operators to improve readability and clear checkpatch issues. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20191214100955.16670-2-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 113 +++++++++--------- 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index e122ef165085..16cb5b31a31d 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -291,7 +291,7 @@ static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode) remain_len = ies_len - (next_ie - ies); ssid_ie[1] = 0; - memcpy(ssid_ie+2, next_ie, remain_len); + memcpy(ssid_ie + 2, next_ie, remain_len); len_diff -= ssid_len_ori; break; @@ -363,14 +363,14 @@ static void issue_beacon(struct adapter *padapter, int timeout_ms) memcpy(pframe, cur_network->ies, cur_network->ie_length); len_diff = update_hidden_ssid( - pframe+_BEACON_IE_OFFSET_ - , cur_network->ie_length-_BEACON_IE_OFFSET_ + pframe + _BEACON_IE_OFFSET_ + , cur_network->ie_length - _BEACON_IE_OFFSET_ , pmlmeinfo->hidden_ssid_mode ); - pframe += (cur_network->ie_length+len_diff); - pattrib->pktlen += (cur_network->ie_length+len_diff); - wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_, - pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen); + pframe += (cur_network->ie_length + len_diff); + pattrib->pktlen += (cur_network->ie_length + len_diff); + wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, + pattrib->pktlen - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_, NULL, &wps_ielen); if (wps_ie && wps_ielen > 0) rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); if (sr != 0) @@ -504,7 +504,7 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da) #if defined(CONFIG_88EU_AP_MODE) if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { - pwps_ie = rtw_get_wps_ie(cur_network->ies+_FIXED_IE_LENGTH_, cur_network->ie_length-_FIXED_IE_LENGTH_, NULL, &wps_ielen); + pwps_ie = rtw_get_wps_ie(cur_network->ies + _FIXED_IE_LENGTH_, cur_network->ie_length - _FIXED_IE_LENGTH_, NULL, &wps_ielen); /* inerset & update wps_probe_resp_ie */ if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) { @@ -522,13 +522,13 @@ static void issue_probersp(struct adapter *padapter, unsigned char *da) pattrib->pktlen += wps_offset; wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */ - if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) { - memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2); - pframe += wps_ielen+2; - pattrib->pktlen += wps_ielen+2; + if ((wps_offset + wps_ielen + 2) <= MAX_IE_SZ) { + memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen + 2); + pframe += wps_ielen + 2; + pattrib->pktlen += wps_ielen + 2; } - if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) { + if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) { memcpy(pframe, premainder_ie, remainder_ielen); pframe += remainder_ielen; pattrib->pktlen += remainder_ielen; @@ -943,7 +943,7 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &pattrib->pktlen); } else { pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &pattrib->pktlen); - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, pstat->bssratelen-8, pstat->bssrateset+8, &pattrib->pktlen); + pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, pstat->bssratelen - 8, pstat->bssrateset + 8, &pattrib->pktlen); } if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) { @@ -952,17 +952,17 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, /* FILL HT CAP INFO IE */ pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_)); if (pbuf && ie_len > 0) { - memcpy(pframe, pbuf, ie_len+2); - pframe += (ie_len+2); - pattrib->pktlen += (ie_len+2); + memcpy(pframe, pbuf, ie_len + 2); + pframe += (ie_len + 2); + pattrib->pktlen += (ie_len + 2); } /* FILL HT ADD INFO IE */ pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_)); if (pbuf && ie_len > 0) { - memcpy(pframe, pbuf, ie_len+2); - pframe += (ie_len+2); - pattrib->pktlen += (ie_len+2); + memcpy(pframe, pbuf, ie_len + 2); + pframe += (ie_len + 2); + pattrib->pktlen += (ie_len + 2); } } @@ -973,10 +973,10 @@ static void issue_asocrsp(struct adapter *padapter, unsigned short status, for (pbuf = ie + _BEACON_IE_OFFSET_;; pbuf += (ie_len + 2)) { pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2))); - if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) { - memcpy(pframe, pbuf, ie_len+2); - pframe += (ie_len+2); - pattrib->pktlen += (ie_len+2); + if (pbuf && !memcmp(pbuf + 2, WMM_PARA_IE, 6)) { + memcpy(pframe, pbuf, ie_len + 2); + pframe += (ie_len + 2); + pattrib->pktlen += (ie_len + 2); break; } @@ -1082,8 +1082,8 @@ static void issue_assocreq(struct adapter *padapter) /* Check if the AP's supported rates are also supported by STA. */ for (j = 0; j < sta_bssrate_len; j++) { /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */ - if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK) - == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) + if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK) + == (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) break; } @@ -1874,7 +1874,7 @@ unsigned int send_beacon(struct adapter *padapter) yield(); rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok)); poll++; - } while ((poll%10) != 0 && !bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); + } while ((poll % 10) != 0 && !bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); } while (!bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); if (padapter->bSurpriseRemoved || padapter->bDriverStopped) @@ -2093,7 +2093,7 @@ static u8 collect_bss_info(struct adapter *padapter, p = rtw_get_ie(bssid->ies + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->ie_length - ie_offset); if (p) { - if (len > (NDIS_802_11_LENGTH_RATES_EX-i)) { + if (len > (NDIS_802_11_LENGTH_RATES_EX - i)) { DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len); return _FAIL; } @@ -2518,7 +2518,7 @@ static unsigned int OnProbeReq(struct adapter *padapter, return _SUCCESS; if (!check_fwstate(pmlmepriv, _FW_LINKED) && - !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) + !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE)) return _SUCCESS; p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, &ielen, @@ -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.ssid_length)) || + if ((ielen != 0 && memcmp((void *)(p + 2), (void *)cur->ssid.ssid, cur->ssid.ssid_length)) || (ielen == 0 && pmlmeinfo->hidden_ssid_mode)) return _SUCCESS; @@ -2583,7 +2583,7 @@ static unsigned int OnBeacon(struct adapter *padapter, } /* check the vendor of the assoc AP */ - pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr)); + pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe + sizeof(struct ieee80211_hdr_3addr), len - sizeof(struct ieee80211_hdr_3addr)); /* update TSF Value */ update_TSF(pmlmeext, pframe, len); @@ -2729,7 +2729,7 @@ static unsigned int OnAuth(struct adapter *padapter, if ((pstat->auth_seq + 1) != seq) { DBG_88E("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", - seq, pstat->auth_seq+1); + seq, pstat->auth_seq + 1); status = _STATS_OUT_OF_AUTH_SEQ_; goto auth_fail; } @@ -2742,7 +2742,7 @@ static unsigned int OnAuth(struct adapter *padapter, pstat->authalg = algorithm; } else { DBG_88E("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", - seq, pstat->auth_seq+1); + seq, pstat->auth_seq + 1); status = _STATS_OUT_OF_AUTH_SEQ_; goto auth_fail; } @@ -2779,7 +2779,7 @@ static unsigned int OnAuth(struct adapter *padapter, } } else { DBG_88E("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", - seq, pstat->auth_seq+1); + seq, pstat->auth_seq + 1); status = _STATS_OUT_OF_AUTH_SEQ_; goto auth_fail; } @@ -2975,7 +2975,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, goto OnAssocReqFail; } else { /* check if ssid match */ - if (memcmp((void *)(p+2), cur->ssid.ssid, cur->ssid.ssid_length)) + if (memcmp((void *)(p + 2), cur->ssid.ssid, cur->ssid.ssid_length)) status = _STATS_FAILURE_; if (ie_len != cur->ssid.ssid_length) @@ -2996,14 +2996,15 @@ static unsigned int OnAssocReq(struct adapter *padapter, status = _STATS_FAILURE_; goto OnAssocReqFail; } else { - memcpy(supportRate, p+2, ie_len); + memcpy(supportRate, p + 2, ie_len); supportRateNum = ie_len; p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); if (p) { if (supportRateNum <= sizeof(supportRate)) { - memcpy(supportRate+supportRateNum, p+2, ie_len); + memcpy(supportRate + supportRateNum, + p + 2, ie_len); supportRateNum += ie_len; } } @@ -3031,7 +3032,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, wpa_ie = elems.rsn_ie; wpa_ie_len = elems.rsn_ie_len; - if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + if (rtw_parse_wpa2_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { pstat->dot8021xalg = 1;/* psk, todo:802.1x */ pstat->wpa_psk |= BIT(1); @@ -3052,7 +3053,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, wpa_ie = elems.wpa_ie; wpa_ie_len = elems.wpa_ie_len; - if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { + if (rtw_parse_wpa_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { pstat->dot8021xalg = 1;/* psk, todo:802.1x */ pstat->wpa_psk |= BIT(0); @@ -3094,7 +3095,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */ /* that the selected registrar of AP is _FLASE */ - if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) { + if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) { if (pmlmepriv->wps_beacon_ie) { u8 selected_registrar = 0; @@ -3131,7 +3132,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, copy_len = min_t(int, wpa_ie_len + 2, sizeof(pstat->wpa_ie)); } if (copy_len > 0) - memcpy(pstat->wpa_ie, wpa_ie-2, copy_len); + memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len); } /* check if there is WMM IE & support WWM-PS */ pstat->flags &= ~WLAN_STA_WME; @@ -3147,13 +3148,13 @@ static unsigned int OnAssocReq(struct adapter *padapter, for (;;) { p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); if (p) { - if (!memcmp(p+2, WMM_IE, 6)) { + if (!memcmp(p + 2, WMM_IE, 6)) { pstat->flags |= WLAN_STA_WME; pstat->qos_option = 1; - pstat->qos_info = *(p+8); + pstat->qos_info = *(p + 8); - pstat->max_sp_len = (pstat->qos_info>>5) & 0x3; + pstat->max_sp_len = (pstat->qos_info >> 5) & 0x3; if ((pstat->qos_info & 0xf) != 0xf) pstat->has_legacy_ac = true; @@ -3162,22 +3163,22 @@ static unsigned int OnAssocReq(struct adapter *padapter, if (pstat->qos_info & 0xf) { if (pstat->qos_info & BIT(0)) - pstat->uapsd_vo = BIT(0)|BIT(1); + pstat->uapsd_vo = BIT(0) | BIT(1); else pstat->uapsd_vo = 0; if (pstat->qos_info & BIT(1)) - pstat->uapsd_vi = BIT(0)|BIT(1); + pstat->uapsd_vi = BIT(0) | BIT(1); else pstat->uapsd_vi = 0; if (pstat->qos_info & BIT(2)) - pstat->uapsd_bk = BIT(0)|BIT(1); + pstat->uapsd_bk = BIT(0) | BIT(1); else pstat->uapsd_bk = 0; if (pstat->qos_info & BIT(3)) - pstat->uapsd_be = BIT(0)|BIT(1); + pstat->uapsd_be = BIT(0) | BIT(1); else pstat->uapsd_be = 0; } @@ -4515,7 +4516,7 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res) /* set per sta rate after updating HT cap. */ set_sta_rate(padapter, psta); rtw_hal_set_hwreg(padapter, HW_VAR_TX_RPT_MAX_MACID, (u8 *)&psta->mac_id); - media_status = (psta->mac_id<<8)|1; /* MACID|OPMODE: 1 means connect */ + media_status = (psta->mac_id << 8) | 1; /* MACID|OPMODE: 1 means connect */ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status); } @@ -4844,7 +4845,7 @@ u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf) pmlmeinfo->state = WIFI_FW_AP_STATE; type = _HW_STATE_AP_; } else if (psetop->mode == Ndis802_11Infrastructure) { - pmlmeinfo->state &= ~(BIT(0)|BIT(1));/* clear state */ + pmlmeinfo->state &= ~(BIT(0) | BIT(1));/* clear state */ pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */ type = _HW_STATE_STATION_; } else if (psetop->mode == Ndis802_11IBSS) { @@ -5040,7 +5041,7 @@ u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf) u8 val8; if (is_client_associated_to_ap(padapter)) - issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100); + issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms / 100, 100); rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL); rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr); @@ -5084,7 +5085,7 @@ static int rtw_scan_ch_decision(struct adapter *padapter, struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; /* clear out first */ - memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num); + memset(out, 0, sizeof(struct rtw_ieee80211_channel) * out_num); /* acquire channels from in */ j = 0; @@ -5263,7 +5264,7 @@ u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf) DBG_88E("r871x_set_stakey_hdl(): enc_algorithm=%d\n", pparm->algorithm); - if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA-4))) { + if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA - 4))) { DBG_88E("r871x_set_stakey_hdl():set_stakey failed, mac_id(aid)=%d\n", psta->mac_id); return H2C_REJECTED; } @@ -5339,8 +5340,8 @@ u8 set_tx_beacon_cmd(struct adapter *padapter) goto exit; } - len_diff = update_hidden_ssid(ptxBeacon_parm->ies+_BEACON_IE_OFFSET_, - ptxBeacon_parm->ie_length-_BEACON_IE_OFFSET_, + len_diff = update_hidden_ssid(ptxBeacon_parm->ies + _BEACON_IE_OFFSET_, + ptxBeacon_parm->ie_length - _BEACON_IE_OFFSET_, pmlmeinfo->hidden_ssid_mode); ptxBeacon_parm->ie_length += len_diff; @@ -5361,7 +5362,7 @@ u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf) peventbuf = (uint *)pbuf; evt_sz = (u16)(*peventbuf & 0xffff); - evt_code = (u8)((*peventbuf>>16) & 0xff); + evt_code = (u8)((*peventbuf >> 16) & 0xff); /* checking if event code is valid */ if (evt_code >= MAX_C2HEVT) { From 99879121bfbb6a815e4699aabd00ae317ca1d215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:27 +0000 Subject: [PATCH 101/353] staging: wfx: fix the cache of rate policies on interface reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Device and driver maintain a cache of rate policies (aka. tx_retry_policy in hardware API). When hif_reset() is sent to hardware, device resets its cache of rate policies. In order to keep driver in sync, it is necessary to do the same on driver. Note, when driver tries to use a rate policy that has not been defined on device, data is sent at 1Mbps. So, this patch should fix abnormal throughput observed sometime after a reset of the interface. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-2-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 3 +-- drivers/staging/wfx/data_tx.h | 1 + drivers/staging/wfx/sta.c | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index df2640a79f02..bc769d1b6bc5 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -249,7 +249,7 @@ static int wfx_tx_policy_upload(struct wfx_vif *wvif) return 0; } -static void wfx_tx_policy_upload_work(struct work_struct *work) +void wfx_tx_policy_upload_work(struct work_struct *work) { struct wfx_vif *wvif = container_of(work, struct wfx_vif, tx_policy_upload_work); @@ -270,7 +270,6 @@ void wfx_tx_policy_init(struct wfx_vif *wvif) spin_lock_init(&cache->lock); INIT_LIST_HEAD(&cache->used); INIT_LIST_HEAD(&cache->free); - INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work); for (i = 0; i < HIF_MIB_NUM_TX_RATE_RETRY_POLICIES; ++i) list_add(&cache->cache[i].link, &cache->free); diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h index 29faa5640516..a0f9ae69baf5 100644 --- a/drivers/staging/wfx/data_tx.h +++ b/drivers/staging/wfx/data_tx.h @@ -61,6 +61,7 @@ struct wfx_tx_priv { } __packed; void wfx_tx_policy_init(struct wfx_vif *wvif); +void wfx_tx_policy_upload_work(struct work_struct *work); void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb); diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 29848a202ab4..471dd15b227f 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -592,6 +592,7 @@ static void wfx_do_unjoin(struct wfx_vif *wvif) wfx_tx_flush(wvif->wdev); hif_keep_alive_period(wvif, 0); hif_reset(wvif, false); + wfx_tx_policy_init(wvif); hif_set_output_power(wvif, wvif->wdev->output_power * 10); wvif->dtim_period = 0; hif_set_macaddr(wvif, wvif->vif->addr); @@ -880,8 +881,10 @@ static int wfx_update_beaconing(struct wfx_vif *wvif) if (wvif->state != WFX_STATE_AP || wvif->beacon_int != conf->beacon_int) { wfx_tx_lock_flush(wvif->wdev); - if (wvif->state != WFX_STATE_PASSIVE) + if (wvif->state != WFX_STATE_PASSIVE) { hif_reset(wvif, false); + wfx_tx_policy_init(wvif); + } wvif->state = WFX_STATE_PASSIVE; wfx_start_ap(wvif); wfx_tx_unlock(wvif->wdev); @@ -1567,6 +1570,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) INIT_WORK(&wvif->set_cts_work, wfx_set_cts_work); INIT_WORK(&wvif->unjoin_work, wfx_unjoin_work); + INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work); mutex_unlock(&wdev->conf_mutex); hif_set_macaddr(wvif, vif->addr); From c594ff7c7cfade844a78484d366c5b4d4dfbf47a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:29 +0000 Subject: [PATCH 102/353] staging: wfx: fix case of lack of tx_retry_policies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some rare cases, driver may not have any available tx_retry_policies. In this case, the driver asks to mac80211 to stop sending data. However, it seems that a race is possible and a few frames can be sent to the driver. In this case, driver can't wait for free tx_retry_policies since wfx_tx() must be atomic. So, this patch fix this case by sending these frames with the special policy number 15. The firmware normally use policy 15 to send internal frames (PS-poll, beacons, etc...). So, it is not a so bad fallback. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-3-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index bc769d1b6bc5..4edf8bb964e6 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -16,7 +16,7 @@ #include "traces.h" #include "hif_tx_mib.h" -#define WFX_INVALID_RATE_ID (0xFF) +#define WFX_INVALID_RATE_ID 15 #define WFX_LINK_ID_NO_ASSOC 15 #define WFX_LINK_ID_GC_TIMEOUT ((unsigned long)(10 * HZ)) @@ -202,6 +202,8 @@ static void wfx_tx_policy_put(struct wfx_vif *wvif, int idx) int usage, locked; struct tx_policy_cache *cache = &wvif->tx_policy_cache; + if (idx == WFX_INVALID_RATE_ID) + return; spin_lock_bh(&cache->lock); locked = list_empty(&cache->free); usage = wfx_tx_policy_release(cache, &cache->cache[idx]); @@ -549,7 +551,8 @@ static u8 wfx_tx_get_rate_id(struct wfx_vif *wvif, rate_id = wfx_tx_policy_get(wvif, tx_info->driver_rates, &tx_policy_renew); - WARN(rate_id == WFX_INVALID_RATE_ID, "unable to get a valid Tx policy"); + if (rate_id == WFX_INVALID_RATE_ID) + dev_warn(wvif->wdev->dev, "unable to get a valid Tx policy"); if (tx_policy_renew) { /* FIXME: It's not so optimal to stop TX queues every now and From 700e39e2d17649587704afcde50e908ec863f27f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:30 +0000 Subject: [PATCH 103/353] staging: wfx: fix counter overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some weird behaviors were observed when connection is really good and packets are small. It appears that sometime, number of packets in queues can exceed 255 and generate an overflow in field usage_count. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-4-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h index a0f9ae69baf5..f63e5d8cf929 100644 --- a/drivers/staging/wfx/data_tx.h +++ b/drivers/staging/wfx/data_tx.h @@ -39,8 +39,8 @@ struct wfx_link_entry { struct tx_policy { struct list_head link; + int usage_count; u8 rates[12]; - u8 usage_count; u8 uploaded; }; From 6673f2636b41ccafbe48e12a1c393b57a95f084a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:32 +0000 Subject: [PATCH 104/353] staging: wfx: use boolean appropriately MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The field 'uploaded' is used as a boolean, so call it a boolean. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-5-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 4 ++-- drivers/staging/wfx/data_tx.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index 4edf8bb964e6..f0003176a314 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -184,7 +184,7 @@ static int wfx_tx_policy_get(struct wfx_vif *wvif, */ entry = list_entry(cache->free.prev, struct tx_policy, link); memcpy(entry->rates, wanted.rates, sizeof(entry->rates)); - entry->uploaded = 0; + entry->uploaded = false; entry->usage_count = 0; idx = entry - cache->cache; } @@ -241,7 +241,7 @@ static int wfx_tx_policy_upload(struct wfx_vif *wvif) dst->terminate = 1; dst->count_init = 1; memcpy(&dst->rates, src->rates, sizeof(src->rates)); - src->uploaded = 1; + src->uploaded = true; arg->num_tx_rate_policies++; } } diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h index f63e5d8cf929..0fc388db62e0 100644 --- a/drivers/staging/wfx/data_tx.h +++ b/drivers/staging/wfx/data_tx.h @@ -41,7 +41,7 @@ struct tx_policy { struct list_head link; int usage_count; u8 rates[12]; - u8 uploaded; + bool uploaded; }; struct tx_policy_cache { From eee5e4c98f307a81c2716ab804e7dc3b66b4c125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:33 +0000 Subject: [PATCH 105/353] staging: wfx: firmware does not support more than 32 total retries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sum of all retries for a Tx frame cannot be superior to 32. There are 4 rates at most. So this patch limits number of retries per rate to 8. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-6-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c index 986a2ef678b9..3b47b6c21ea1 100644 --- a/drivers/staging/wfx/main.c +++ b/drivers/staging/wfx/main.c @@ -289,7 +289,7 @@ struct wfx_dev *wfx_init_common(struct device *dev, hw->sta_data_size = sizeof(struct wfx_sta_priv); hw->queues = 4; hw->max_rates = 8; - hw->max_rate_tries = 15; + hw->max_rate_tries = 8; hw->extra_tx_headroom = sizeof(struct hif_sl_msg_hdr) + sizeof(struct hif_msg) + sizeof(struct hif_req_tx) From 7e1af13225fb0f3c3c75c2b03d9806fecd9f11bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:34 +0000 Subject: [PATCH 106/353] staging: wfx: fix rate control handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A tx_retry_policy (the equivalent of a list of ieee80211_tx_rate in hardware API) is not able to include a rate multiple time. So currently, the driver merges the identical rates from the policy provided by minstrel (and it try to do the best choice it can in the associated flags) before to sent it to firmware. Until now, when rates are merged, field "count" is set to max(count1, count2). But, it means that the sum of retries for all rates could be far less than initial number of retries. So, this patch changes the value of field "count" to count1 + count2. Thus, sum of all retries for all rates stay the same. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-7-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index f0003176a314..a24a63b70014 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -524,9 +524,9 @@ static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates) for (i = 0; i < IEEE80211_TX_MAX_RATES - 1; i++) { if (rates[i + 1].idx == rates[i].idx && rates[i].idx != -1) { - rates[i].count = - max_t(int, rates[i].count, - rates[i + 1].count); + rates[i].count += rates[i + 1].count; + if (rates[i].count > 15) + rates[i].count = 15; rates[i + 1].idx = -1; rates[i + 1].count = 0; From d1fd97b4d843360863a7a7dcf3c7ea1b46e9f863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:36 +0000 Subject: [PATCH 107/353] staging: wfx: ensure that retry policy always fallbacks to MCS0 / 1Mbps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When not using HT mode, minstrel always includes 1Mbps as fallback rate. But, when using HT mode, this fallback is not included. Yet, it seems that it could save some frames. So, this patch add it unconditionally. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-8-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index a24a63b70014..29529e26c974 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -538,6 +538,17 @@ static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates) } } } while (!finished); + // Ensure that MCS0 or 1Mbps is present at the end of the retry list + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + if (rates[i].idx == 0) + break; + if (rates[i].idx == -1) { + rates[i].idx = 0; + rates[i].count = 8; // == hw->max_rate_tries + rates[i].flags = rates[i - 1].flags & IEEE80211_TX_RC_MCS; + break; + } + } // All retries use long GI for (i = 1; i < IEEE80211_TX_MAX_RATES; i++) rates[i].flags &= ~IEEE80211_TX_RC_SHORT_GI; From 8608ecdba5ce98031237add7727f8b9df457e381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:37 +0000 Subject: [PATCH 108/353] staging: wfx: detect race condition in WEP authentication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current code has a special case to handle association with WEP. Before to rework the tx data handling, let's try to detect any possible misuse of this code. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-9-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/queue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index c7ee90888f69..680fed31cefb 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -422,6 +422,7 @@ static bool hif_handle_tx_data(struct wfx_vif *wvif, struct sk_buff *skb, break; case do_wep: wfx_tx_lock(wvif->wdev); + WARN_ON(wvif->wep_pending_skb); wvif->wep_default_key_id = tx_priv->hw_key->keyidx; wvif->wep_pending_skb = skb; if (!schedule_work(&wvif->wep_key_work)) From d3d00313bf464423dfd278978d115d9a75875caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:38 +0000 Subject: [PATCH 109/353] staging: wfx: fix hif_set_mfp() with big endian hosts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct hif_mib_protected_mgmt_policy is an array of u8. There is no reason to swap its bytes. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-10-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx_mib.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index bb091e395ff5..9be74881c56c 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -147,7 +147,6 @@ static inline int hif_set_mfp(struct wfx_vif *wvif, bool capable, bool required) } if (!required) val.unpmf_allowed = 1; - cpu_to_le32s((u32 *) &val); return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_PROTECTED_MGMT_POLICY, &val, sizeof(val)); From 983b39337d07c0d80f73af94659098830ae2f864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:40 +0000 Subject: [PATCH 110/353] staging: wfx: fix wrong error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver checks that the number of retries made by the device is coherent with the rate policy. However, this check make sense only if the device has returned RETRY_EXCEEDED. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-11-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index 29529e26c974..b13d7341f8bb 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -748,7 +748,9 @@ void wfx_tx_confirm_cb(struct wfx_vif *wvif, struct hif_cnf_tx *arg) rate = &tx_info->status.rates[i]; if (rate->idx < 0) break; - if (tx_count < rate->count && arg->status && arg->ack_failures) + if (tx_count < rate->count && + arg->status == HIF_STATUS_RETRY_EXCEEDED && + arg->ack_failures) dev_dbg(wvif->wdev->dev, "all retries were not consumed: %d != %d\n", rate->count, tx_count); if (tx_count <= rate->count && tx_count && From 46112d557d065f096b4ac41dae9a2be9399a6621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:41 +0000 Subject: [PATCH 111/353] staging: wfx: increase SPI bus frequency limit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The chip has now proven that it can run at 50MHz on any boards without any problem. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-12-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/bus_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wfx/bus_spi.c b/drivers/staging/wfx/bus_spi.c index ab0cda1e124f..44fc42bb43a0 100644 --- a/drivers/staging/wfx/bus_spi.c +++ b/drivers/staging/wfx/bus_spi.c @@ -183,7 +183,7 @@ static int wfx_spi_probe(struct spi_device *func) if (func->bits_per_word != 16 && func->bits_per_word != 8) dev_warn(&func->dev, "unusual bits/word value: %d\n", func->bits_per_word); - if (func->max_speed_hz > 49000000) + if (func->max_speed_hz > 50000000) dev_warn(&func->dev, "%dHz is a very high speed\n", func->max_speed_hz); From b025605cc4462b482db8e75dcb5019fa9a016b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:42 +0000 Subject: [PATCH 112/353] staging: wfx: don't print useless error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During chip probing, if error does not come from secure boot (for exemple when firmware has been found), others errors probably appears. It is not necessary to say to user that the error does not come from secure boot. So, drop the message saying "no error reported by secure boot". BTW, we take the opportunity to simplify print_boot_status(). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-13-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/fwio.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/staging/wfx/fwio.c b/drivers/staging/wfx/fwio.c index dbf8bda71ff7..47e627bf0f8e 100644 --- a/drivers/staging/wfx/fwio.c +++ b/drivers/staging/wfx/fwio.c @@ -61,7 +61,7 @@ #define DCA_TIMEOUT 50 // milliseconds #define WAKEUP_TIMEOUT 200 // milliseconds -static const char * const fwio_error_strings[] = { +static const char * const fwio_errors[] = { [ERR_INVALID_SEC_TYPE] = "Invalid section type or wrong encryption", [ERR_SIG_VERIF_FAILED] = "Signature verification failed", [ERR_AES_CTRL_KEY] = "AES control key not initialized", @@ -220,22 +220,16 @@ static int upload_firmware(struct wfx_dev *wdev, const u8 *data, size_t len) static void print_boot_status(struct wfx_dev *wdev) { - u32 val32; + u32 reg; - sram_reg_read(wdev, WFX_STATUS_INFO, &val32); - if (val32 == 0x12345678) { - dev_info(wdev->dev, "no error reported by secure boot\n"); - } else { - sram_reg_read(wdev, WFX_ERR_INFO, &val32); - if (val32 < ARRAY_SIZE(fwio_error_strings) && - fwio_error_strings[val32]) - dev_info(wdev->dev, "secure boot error: %s\n", - fwio_error_strings[val32]); - else - dev_info(wdev->dev, - "secure boot error: Unknown (0x%02x)\n", - val32); - } + sram_reg_read(wdev, WFX_STATUS_INFO, ®); + if (reg == 0x12345678) + return; + sram_reg_read(wdev, WFX_ERR_INFO, ®); + if (reg < ARRAY_SIZE(fwio_errors) && fwio_errors[reg]) + dev_info(wdev->dev, "secure boot: %s\n", fwio_errors[reg]); + else + dev_info(wdev->dev, "secure boot: Error %#02x\n", reg); } static int load_firmware_secure(struct wfx_dev *wdev) From 88d54d6e15df476110e38b390862b7c8defb63d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:44 +0000 Subject: [PATCH 113/353] staging: wfx: avoid double warning when no more tx policy are available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, number of available tx retry policies is checked two times. Only one is sufficient. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-14-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index b13d7341f8bb..a1853056ebf1 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -169,7 +169,8 @@ static int wfx_tx_policy_get(struct wfx_vif *wvif, wfx_tx_policy_build(wvif, &wanted, rates); spin_lock_bh(&cache->lock); - if (WARN_ON(list_empty(&cache->free))) { + if (list_empty(&cache->free)) { + WARN(1, "unable to get a valid Tx policy"); spin_unlock_bh(&cache->lock); return WFX_INVALID_RATE_ID; } From 42edb537a3bb2b65733eb975b6ae405a9f5b43e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:46 +0000 Subject: [PATCH 114/353] staging: wfx: improve error message on unexpected confirmation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When driver receives an unexpected answer from the device, it shows "unsupported HIF ID". That message does not represent the real error. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-15-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_rx.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/staging/wfx/hif_rx.c b/drivers/staging/wfx/hif_rx.c index 820de216be0c..1494ad5a507b 100644 --- a/drivers/staging/wfx/hif_rx.c +++ b/drivers/staging/wfx/hif_rx.c @@ -358,7 +358,12 @@ void wfx_handle_rx(struct wfx_dev *wdev, struct sk_buff *skb) goto free; } } - dev_err(wdev->dev, "unsupported HIF ID %02x\n", hif_id); + if (hif_id & 0x80) + dev_err(wdev->dev, "unsupported HIF indication: ID %02x\n", + hif_id); + else + dev_err(wdev->dev, "unexpected HIF confirmation: ID %02x\n", + hif_id); free: dev_kfree_skb(skb); } From 50e5ac346fa7764fb480932a77c248ee67c407f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:48 +0000 Subject: [PATCH 115/353] staging: wfx: take advantage of IS_ERR_OR_NULL() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Obviously, current code can be replaced by IS_ERR_OR_NULL(). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-16-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c index 3b47b6c21ea1..cf4bcb14a12d 100644 --- a/drivers/staging/wfx/main.c +++ b/drivers/staging/wfx/main.c @@ -182,7 +182,7 @@ struct gpio_desc *wfx_get_gpio(struct device *dev, int override, } else { ret = devm_gpiod_get(dev, label, GPIOD_OUT_LOW); } - if (IS_ERR(ret) || !ret) { + if (IS_ERR_OR_NULL(ret)) { if (!ret || PTR_ERR(ret) == -ENOENT) dev_warn(dev, "gpio %s is not defined\n", label); else From 9e25ec9a2c5a0561141075f17a6e4faa4180af22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:51 +0000 Subject: [PATCH 116/353] staging: wfx: uniformize naming rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In wfx driver, when a function is used as a struct member, its name is the name of the member prefixed with "wfx_". This patch apply this rule to wfx_spi_remove(). Also remove the useless comment above the function. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-17-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/bus_spi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wfx/bus_spi.c b/drivers/staging/wfx/bus_spi.c index 44fc42bb43a0..0a055c4041af 100644 --- a/drivers/staging/wfx/bus_spi.c +++ b/drivers/staging/wfx/bus_spi.c @@ -223,8 +223,7 @@ static int wfx_spi_probe(struct spi_device *func) return ret; } -/* Disconnect Function to be called by SPI stack when device is disconnected */ -static int wfx_spi_disconnect(struct spi_device *func) +static int wfx_spi_remove(struct spi_device *func) { struct wfx_spi_priv *bus = spi_get_drvdata(func); @@ -263,5 +262,5 @@ struct spi_driver wfx_spi_driver = { }, .id_table = wfx_spi_id, .probe = wfx_spi_probe, - .remove = wfx_spi_disconnect, + .remove = wfx_spi_remove, }; From faa4763ffbce2b7e3a6fab841033d27421317943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:52 +0000 Subject: [PATCH 117/353] staging: wfx: use meaningful names for CFG_BYTE_ORDER_* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This new naming allows to save a comment. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-18-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/bus_spi.c | 2 ++ drivers/staging/wfx/fwio.c | 2 +- drivers/staging/wfx/hwio.h | 15 +++++---------- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wfx/bus_spi.c b/drivers/staging/wfx/bus_spi.c index 0a055c4041af..40bc33035de2 100644 --- a/drivers/staging/wfx/bus_spi.c +++ b/drivers/staging/wfx/bus_spi.c @@ -107,6 +107,8 @@ static int wfx_spi_copy_to_io(void *priv, unsigned int addr, cpu_to_le16s(®addr); + // Register address and CONFIG content always use 16bit big endian + // ("BADC" order) if (bus->need_swab) swab16s(®addr); if (bus->need_swab && addr == WFX_REG_CONFIG) diff --git a/drivers/staging/wfx/fwio.c b/drivers/staging/wfx/fwio.c index 47e627bf0f8e..9d61082c1e6c 100644 --- a/drivers/staging/wfx/fwio.c +++ b/drivers/staging/wfx/fwio.c @@ -339,7 +339,7 @@ int wfx_init_device(struct wfx_dev *wdev) ktime_t now, start; u32 reg; - reg = CFG_DIRECT_ACCESS_MODE | CFG_CPU_RESET | CFG_WORD_MODE2; + reg = CFG_DIRECT_ACCESS_MODE | CFG_CPU_RESET | CFG_BYTE_ORDER_ABCD; if (wdev->pdata.use_rising_clk) reg |= CFG_CLK_RISE_EDGE; ret = config_reg_write(wdev, reg); diff --git a/drivers/staging/wfx/hwio.h b/drivers/staging/wfx/hwio.h index b2c1a66de963..4b6ef061b40b 100644 --- a/drivers/staging/wfx/hwio.h +++ b/drivers/staging/wfx/hwio.h @@ -37,16 +37,11 @@ int ahb_reg_write(struct wfx_dev *wdev, u32 addr, u32 val); #define CFG_ERR_HOST_NO_IN_QUEUE 0x00000040 #define CFG_ERR_HOST_CRC_MISS 0x00000080 // only with SDIO #define CFG_SPI_IGNORE_CS 0x00000080 // only with SPI -/* Bytes ordering (only writable in SPI): */ -#define CFG_WORD_MODE_MASK 0x00000300 -/* - * B1,B0,B3,B2 (In SPI, register address and - * CONFIG data always use this mode) - */ -#define CFG_WORD_MODE0 0x00000000 -#define CFG_WORD_MODE1 0x00000100 // B3,B2,B1,B0 -#define CFG_WORD_MODE2 0x00000200 // B0,B1,B2,B3 (SDIO) -#define CFG_DIRECT_ACCESS_MODE 0x00000400 // Direct or queue access mode +#define CFG_BYTE_ORDER_MASK 0x00000300 // only writable with SPI +#define CFG_BYTE_ORDER_BADC 0x00000000 +#define CFG_BYTE_ORDER_DCBA 0x00000100 +#define CFG_BYTE_ORDER_ABCD 0x00000200 // SDIO always use this value +#define CFG_DIRECT_ACCESS_MODE 0x00000400 #define CFG_PREFETCH_AHB 0x00000800 #define CFG_DISABLE_CPU_CLK 0x00001000 #define CFG_PREFETCH_SRAM 0x00002000 From 1380b9397706d1cc14cff48a7f3a6b8aa97ea2ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:54 +0000 Subject: [PATCH 118/353] staging: wfx: remove useless include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hif_tx.c does not use any struct skb. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-19-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index cb7cddcb9815..e8c2bd1efbac 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -6,7 +6,6 @@ * Copyright (c) 2017-2019, Silicon Laboratories, Inc. * Copyright (c) 2010, ST-Ericsson */ -#include #include #include "hif_tx.h" From faffec8883cc2138fccc7a0c60f26bf9845d6b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:55 +0000 Subject: [PATCH 119/353] staging: wfx: simplify variable assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Attribute "aborted" and argument "aborted" are both booleans. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-20-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index 35fcf9119f96..a6c93400a7ba 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -16,7 +16,7 @@ static void __ieee80211_scan_completed_compat(struct ieee80211_hw *hw, bool aborted) { struct cfg80211_scan_info info = { - .aborted = aborted ? 1 : 0, + .aborted = aborted, }; ieee80211_scan_completed(hw, &info); From eddd8585fb46db6fa701efc963a93477591cd736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:56 +0000 Subject: [PATCH 120/353] staging: wfx: make conditions easier to read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We prefer series of simple boolean conditions than computing bitmasks. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-21-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 471dd15b227f..7f4eaa8e6d84 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -1055,9 +1055,11 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, } } - if (changed & - (BSS_CHANGED_BEACON | BSS_CHANGED_AP_PROBE_RESP | - BSS_CHANGED_BSSID | BSS_CHANGED_SSID | BSS_CHANGED_IBSS)) { + if (changed & BSS_CHANGED_BEACON || + changed & BSS_CHANGED_AP_PROBE_RESP || + changed & BSS_CHANGED_BSSID || + changed & BSS_CHANGED_SSID || + changed & BSS_CHANGED_IBSS) { wvif->beacon_int = info->beacon_int; wfx_update_beaconing(wvif); wfx_upload_beacon(wvif); @@ -1095,10 +1097,11 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BSSID) do_join = true; - if (changed & - (BSS_CHANGED_ASSOC | BSS_CHANGED_BSSID | - BSS_CHANGED_IBSS | BSS_CHANGED_BASIC_RATES | - BSS_CHANGED_HT)) { + if (changed & BSS_CHANGED_ASSOC || + changed & BSS_CHANGED_BSSID || + changed & BSS_CHANGED_IBSS || + changed & BSS_CHANGED_BASIC_RATES || + changed & BSS_CHANGED_HT) { if (info->assoc) { if (wvif->state < WFX_STATE_PRE_STA) { ieee80211_connection_loss(vif); @@ -1120,9 +1123,9 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, } /* ERP Protection */ - if (changed & (BSS_CHANGED_ASSOC | - BSS_CHANGED_ERP_CTS_PROT | - BSS_CHANGED_ERP_PREAMBLE)) { + if (changed & BSS_CHANGED_ASSOC || + changed & BSS_CHANGED_ERP_CTS_PROT || + changed & BSS_CHANGED_ERP_PREAMBLE) { u32 prev_erp_info = wvif->erp_info; if (info->use_cts_prot) @@ -1139,10 +1142,10 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, schedule_work(&wvif->set_cts_work); } - if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_SLOT)) + if (changed & BSS_CHANGED_ASSOC || changed & BSS_CHANGED_ERP_SLOT) hif_slot_time(wvif, info->use_short_slot ? 9 : 20); - if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_CQM)) { + if (changed & BSS_CHANGED_ASSOC || changed & BSS_CHANGED_CQM) { struct hif_mib_rcpi_rssi_threshold th = { .rolling_average_count = 8, .detection = 1, From 30cfffb776ec5aa5f3f51184ff08f83c06ecb321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:58 +0000 Subject: [PATCH 121/353] staging: wfx: ensure that traces never modify arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no reason for a trace to change any bit of the argument. So, let's make sure that is the case by declaring the arguments constant. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-22-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/traces.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wfx/traces.h b/drivers/staging/wfx/traces.h index 3f6198ab2235..30c6a13f0e22 100644 --- a/drivers/staging/wfx/traces.h +++ b/drivers/staging/wfx/traces.h @@ -153,7 +153,7 @@ hif_mib_list_enum #define hif_mib_list hif_mib_list_enum { -1, NULL } DECLARE_EVENT_CLASS(hif_data, - TP_PROTO(struct hif_msg *hif, int tx_fill_level, bool is_recv), + TP_PROTO(const struct hif_msg *hif, int tx_fill_level, bool is_recv), TP_ARGS(hif, tx_fill_level, is_recv), TP_STRUCT__entry( __field(int, tx_fill_level) @@ -203,12 +203,12 @@ DECLARE_EVENT_CLASS(hif_data, ) ); DEFINE_EVENT(hif_data, hif_send, - TP_PROTO(struct hif_msg *hif, int tx_fill_level, bool is_recv), + TP_PROTO(const struct hif_msg *hif, int tx_fill_level, bool is_recv), TP_ARGS(hif, tx_fill_level, is_recv)); #define _trace_hif_send(hif, tx_fill_level)\ trace_hif_send(hif, tx_fill_level, false) DEFINE_EVENT(hif_data, hif_recv, - TP_PROTO(struct hif_msg *hif, int tx_fill_level, bool is_recv), + TP_PROTO(const struct hif_msg *hif, int tx_fill_level, bool is_recv), TP_ARGS(hif, tx_fill_level, is_recv)); #define _trace_hif_recv(hif, tx_fill_level)\ trace_hif_recv(hif, tx_fill_level, true) @@ -359,7 +359,8 @@ TRACE_EVENT(bh_stats, trace_bh_stats(ind, req, cnf, busy, release) TRACE_EVENT(tx_stats, - TP_PROTO(struct hif_cnf_tx *tx_cnf, struct sk_buff *skb, int delay), + TP_PROTO(const struct hif_cnf_tx *tx_cnf, const struct sk_buff *skb, + int delay), TP_ARGS(tx_cnf, skb, delay), TP_STRUCT__entry( __field(int, pkt_id) @@ -375,8 +376,9 @@ TRACE_EVENT(tx_stats, // Keep sync with wfx_rates definition in main.c static const int hw_rate[] = { 0, 1, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13 }; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *rates = tx_info->driver_rates; + const struct ieee80211_tx_info *tx_info = + (const struct ieee80211_tx_info *)skb->cb; + const struct ieee80211_tx_rate *rates = tx_info->driver_rates; int i; __entry->pkt_id = tx_cnf->packet_id; From 36f7e3acaac6be7da831b9a0c31022954f79216d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:14:59 +0000 Subject: [PATCH 122/353] staging: wfx: ensure that received hif messages are never modified MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are no real reason to modify the data received from device. So, let's mark the arguments constant. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-23-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_rx.c | 8 ++- drivers/staging/wfx/data_rx.h | 4 +- drivers/staging/wfx/data_tx.c | 2 +- drivers/staging/wfx/data_tx.h | 2 +- drivers/staging/wfx/hif_rx.c | 94 +++++++++++++++++-------------- drivers/staging/wfx/scan.c | 3 +- drivers/staging/wfx/scan.h | 3 +- drivers/staging/wfx/secure_link.h | 8 ++- drivers/staging/wfx/sta.c | 2 +- drivers/staging/wfx/sta.h | 2 +- 10 files changed, 72 insertions(+), 56 deletions(-) diff --git a/drivers/staging/wfx/data_rx.c b/drivers/staging/wfx/data_rx.c index e7fcce8d0cc4..d460c0ffca1f 100644 --- a/drivers/staging/wfx/data_rx.c +++ b/drivers/staging/wfx/data_rx.c @@ -48,7 +48,9 @@ static int wfx_handle_pspoll(struct wfx_vif *wvif, struct sk_buff *skb) return 0; } -static int wfx_drop_encrypt_data(struct wfx_dev *wdev, struct hif_ind_rx *arg, struct sk_buff *skb) +static int wfx_drop_encrypt_data(struct wfx_dev *wdev, + const struct hif_ind_rx *arg, + struct sk_buff *skb) { struct ieee80211_hdr *frame = (struct ieee80211_hdr *) skb->data; size_t hdrlen = ieee80211_hdrlen(frame->frame_control); @@ -98,8 +100,8 @@ static int wfx_drop_encrypt_data(struct wfx_dev *wdev, struct hif_ind_rx *arg, s } -void wfx_rx_cb(struct wfx_vif *wvif, struct hif_ind_rx *arg, - struct sk_buff *skb) +void wfx_rx_cb(struct wfx_vif *wvif, + const struct hif_ind_rx *arg, struct sk_buff *skb) { int link_id = arg->rx_flags.peer_sta_id; struct ieee80211_rx_status *hdr = IEEE80211_SKB_RXCB(skb); diff --git a/drivers/staging/wfx/data_rx.h b/drivers/staging/wfx/data_rx.h index a50ce352bc5e..61c28bfd2a37 100644 --- a/drivers/staging/wfx/data_rx.h +++ b/drivers/staging/wfx/data_rx.h @@ -13,7 +13,7 @@ struct wfx_vif; struct sk_buff; -void wfx_rx_cb(struct wfx_vif *wvif, struct hif_ind_rx *arg, - struct sk_buff *skb); +void wfx_rx_cb(struct wfx_vif *wvif, + const struct hif_ind_rx *arg, struct sk_buff *skb); #endif /* WFX_DATA_RX_H */ diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index a1853056ebf1..b2a325c47b2d 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -720,7 +720,7 @@ drop: ieee80211_tx_status_irqsafe(wdev->hw, skb); } -void wfx_tx_confirm_cb(struct wfx_vif *wvif, struct hif_cnf_tx *arg) +void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg) { int i; int tx_count; diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h index 0fc388db62e0..078d0cfc521a 100644 --- a/drivers/staging/wfx/data_tx.h +++ b/drivers/staging/wfx/data_tx.h @@ -65,7 +65,7 @@ void wfx_tx_policy_upload_work(struct work_struct *work); void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb); -void wfx_tx_confirm_cb(struct wfx_vif *wvif, struct hif_cnf_tx *arg); +void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg); void wfx_skb_dtor(struct wfx_dev *wdev, struct sk_buff *skb); int wfx_unmap_link(struct wfx_vif *wvif, int link_id); diff --git a/drivers/staging/wfx/hif_rx.c b/drivers/staging/wfx/hif_rx.c index 1494ad5a507b..8a3ccdc60b7d 100644 --- a/drivers/staging/wfx/hif_rx.c +++ b/drivers/staging/wfx/hif_rx.c @@ -18,8 +18,8 @@ #include "secure_link.h" #include "hif_api_cmd.h" -static int hif_generic_confirm(struct wfx_dev *wdev, struct hif_msg *hif, - void *buf) +static int hif_generic_confirm(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) { // All confirm messages start with status int status = le32_to_cpu(*((__le32 *) buf)); @@ -59,9 +59,10 @@ static int hif_generic_confirm(struct wfx_dev *wdev, struct hif_msg *hif, return status; } -static int hif_tx_confirm(struct wfx_dev *wdev, struct hif_msg *hif, void *buf) +static int hif_tx_confirm(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) { - struct hif_cnf_tx *body = buf; + const struct hif_cnf_tx *body = buf; struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); WARN_ON(!wvif); @@ -72,11 +73,12 @@ static int hif_tx_confirm(struct wfx_dev *wdev, struct hif_msg *hif, void *buf) return 0; } -static int hif_multi_tx_confirm(struct wfx_dev *wdev, struct hif_msg *hif, - void *buf) +static int hif_multi_tx_confirm(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) { - struct hif_cnf_multi_transmit *body = buf; - struct hif_cnf_tx *buf_loc = (struct hif_cnf_tx *) &body->tx_conf_payload; + const struct hif_cnf_multi_transmit *body = buf; + const struct hif_cnf_tx *buf_loc = + (const struct hif_cnf_tx *)&body->tx_conf_payload; struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); int count = body->num_tx_confs; int i; @@ -93,10 +95,10 @@ static int hif_multi_tx_confirm(struct wfx_dev *wdev, struct hif_msg *hif, return 0; } -static int hif_startup_indication(struct wfx_dev *wdev, struct hif_msg *hif, - void *buf) +static int hif_startup_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) { - struct hif_ind_startup *body = buf; + const struct hif_ind_startup *body = buf; if (body->status || body->firmware_type > 4) { dev_err(wdev->dev, "received invalid startup indication"); @@ -112,8 +114,8 @@ static int hif_startup_indication(struct wfx_dev *wdev, struct hif_msg *hif, return 0; } -static int hif_wakeup_indication(struct wfx_dev *wdev, struct hif_msg *hif, - void *buf) +static int hif_wakeup_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) { if (!wdev->pdata.gpio_wakeup || !gpiod_get_value(wdev->pdata.gpio_wakeup)) { @@ -123,25 +125,27 @@ static int hif_wakeup_indication(struct wfx_dev *wdev, struct hif_msg *hif, return 0; } -static int hif_keys_indication(struct wfx_dev *wdev, struct hif_msg *hif, - void *buf) +static int hif_keys_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) { - struct hif_ind_sl_exchange_pub_keys *body = buf; + const struct hif_ind_sl_exchange_pub_keys *body = buf; + u8 pubkey[API_NCP_PUB_KEY_SIZE]; - // Compatibility with legacy secure link - if (body->status == SL_PUB_KEY_EXCHANGE_STATUS_SUCCESS) - body->status = 0; - if (body->status) + // SL_PUB_KEY_EXCHANGE_STATUS_SUCCESS is used by legacy secure link + if (body->status && body->status != SL_PUB_KEY_EXCHANGE_STATUS_SUCCESS) dev_warn(wdev->dev, "secure link negociation error\n"); - wfx_sl_check_pubkey(wdev, body->ncp_pub_key, body->ncp_pub_key_mac); + memcpy(pubkey, body->ncp_pub_key, sizeof(pubkey)); + memreverse(pubkey, sizeof(pubkey)); + wfx_sl_check_pubkey(wdev, pubkey, body->ncp_pub_key_mac); return 0; } -static int hif_receive_indication(struct wfx_dev *wdev, struct hif_msg *hif, - void *buf, struct sk_buff *skb) +static int hif_receive_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, + const void *buf, struct sk_buff *skb) { struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); - struct hif_ind_rx *body = buf; + const struct hif_ind_rx *body = buf; if (!wvif) { dev_warn(wdev->dev, "ignore rx data for non-existent vif %d\n", @@ -154,11 +158,11 @@ static int hif_receive_indication(struct wfx_dev *wdev, struct hif_msg *hif, return 0; } -static int hif_event_indication(struct wfx_dev *wdev, struct hif_msg *hif, - void *buf) +static int hif_event_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) { struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); - struct hif_ind_event *body = buf; + const struct hif_ind_event *body = buf; struct wfx_hif_event *event; int first; @@ -183,7 +187,8 @@ static int hif_event_indication(struct wfx_dev *wdev, struct hif_msg *hif, } static int hif_pm_mode_complete_indication(struct wfx_dev *wdev, - struct hif_msg *hif, void *buf) + const struct hif_msg *hif, + const void *buf) { struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); @@ -194,10 +199,11 @@ static int hif_pm_mode_complete_indication(struct wfx_dev *wdev, } static int hif_scan_complete_indication(struct wfx_dev *wdev, - struct hif_msg *hif, void *buf) + const struct hif_msg *hif, + const void *buf) { struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); - struct hif_ind_scan_cmpl *body = buf; + const struct hif_ind_scan_cmpl *body = buf; WARN_ON(!wvif); wfx_scan_complete_cb(wvif, body); @@ -206,7 +212,8 @@ static int hif_scan_complete_indication(struct wfx_dev *wdev, } static int hif_join_complete_indication(struct wfx_dev *wdev, - struct hif_msg *hif, void *buf) + const struct hif_msg *hif, + const void *buf) { struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); @@ -217,10 +224,11 @@ static int hif_join_complete_indication(struct wfx_dev *wdev, } static int hif_suspend_resume_indication(struct wfx_dev *wdev, - struct hif_msg *hif, void *buf) + const struct hif_msg *hif, + const void *buf) { struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); - struct hif_ind_suspend_resume_tx *body = buf; + const struct hif_ind_suspend_resume_tx *body = buf; WARN_ON(!wvif); wfx_suspend_resume(wvif, body); @@ -228,10 +236,10 @@ static int hif_suspend_resume_indication(struct wfx_dev *wdev, return 0; } -static int hif_error_indication(struct wfx_dev *wdev, struct hif_msg *hif, - void *buf) +static int hif_error_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) { - struct hif_ind_error *body = buf; + const struct hif_ind_error *body = buf; u8 *pRollback = (u8 *) body->data; u32 *pStatus = (u32 *) body->data; @@ -268,10 +276,10 @@ static int hif_error_indication(struct wfx_dev *wdev, struct hif_msg *hif, return 0; } -static int hif_generic_indication(struct wfx_dev *wdev, struct hif_msg *hif, - void *buf) +static int hif_generic_indication(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf) { - struct hif_ind_generic *body = buf; + const struct hif_ind_generic *body = buf; switch (body->indication_type) { case HIF_GENERIC_INDICATION_TYPE_RAW: @@ -299,9 +307,10 @@ static int hif_generic_indication(struct wfx_dev *wdev, struct hif_msg *hif, } static int hif_exception_indication(struct wfx_dev *wdev, - struct hif_msg *hif, void *buf) + const struct hif_msg *hif, const void *buf) { size_t len = hif->len - 4; // drop header + dev_err(wdev->dev, "firmware exception\n"); print_hex_dump_bytes("Dump: ", DUMP_PREFIX_NONE, buf, len); wdev->chip_frozen = 1; @@ -311,7 +320,8 @@ static int hif_exception_indication(struct wfx_dev *wdev, static const struct { int msg_id; - int (*handler)(struct wfx_dev *wdev, struct hif_msg *hif, void *buf); + int (*handler)(struct wfx_dev *wdev, + const struct hif_msg *hif, const void *buf); } hif_handlers[] = { /* Confirmations */ { HIF_CNF_ID_TX, hif_tx_confirm }, @@ -335,7 +345,7 @@ static const struct { void wfx_handle_rx(struct wfx_dev *wdev, struct sk_buff *skb) { int i; - struct hif_msg *hif = (struct hif_msg *) skb->data; + const struct hif_msg *hif = (const struct hif_msg *)skb->data; int hif_id = hif->id; if (hif_id == HIF_IND_ID_RX) { diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index a6c93400a7ba..45e78c5722ff 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -267,7 +267,8 @@ void wfx_scan_failed_cb(struct wfx_vif *wvif) } } -void wfx_scan_complete_cb(struct wfx_vif *wvif, struct hif_ind_scan_cmpl *arg) +void wfx_scan_complete_cb(struct wfx_vif *wvif, + const struct hif_ind_scan_cmpl *arg) { if (cancel_delayed_work_sync(&wvif->scan.timeout) > 0) { wvif->scan.status = 1; diff --git a/drivers/staging/wfx/scan.h b/drivers/staging/wfx/scan.h index b4ddd0771a9b..c7c0ab178c87 100644 --- a/drivers/staging/wfx/scan.h +++ b/drivers/staging/wfx/scan.h @@ -36,7 +36,8 @@ int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *req); void wfx_scan_work(struct work_struct *work); void wfx_scan_timeout(struct work_struct *work); -void wfx_scan_complete_cb(struct wfx_vif *wvif, struct hif_ind_scan_cmpl *arg); +void wfx_scan_complete_cb(struct wfx_vif *wvif, + const struct hif_ind_scan_cmpl *arg); void wfx_scan_failed_cb(struct wfx_vif *wvif); #endif /* WFX_SCAN_H */ diff --git a/drivers/staging/wfx/secure_link.h b/drivers/staging/wfx/secure_link.h index 666b26e5308d..c3d055b2f8b1 100644 --- a/drivers/staging/wfx/secure_link.h +++ b/drivers/staging/wfx/secure_link.h @@ -25,14 +25,16 @@ static inline int wfx_sl_decode(struct wfx_dev *wdev, struct hif_sl_msg *m) return -EIO; } -static inline int wfx_sl_encode(struct wfx_dev *wdev, struct hif_msg *input, +static inline int wfx_sl_encode(struct wfx_dev *wdev, + const struct hif_msg *input, struct hif_sl_msg *output) { return -EIO; } -static inline int wfx_sl_check_pubkey(struct wfx_dev *wdev, u8 *ncp_pubkey, - u8 *ncp_pubmac) +static inline int wfx_sl_check_pubkey(struct wfx_dev *wdev, + const u8 *ncp_pubkey, + const u8 *ncp_pubmac) { return -EIO; } diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 7f4eaa8e6d84..b4bb5b653e64 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -1345,7 +1345,7 @@ int wfx_ampdu_action(struct ieee80211_hw *hw, } void wfx_suspend_resume(struct wfx_vif *wvif, - struct hif_ind_suspend_resume_tx *arg) + const struct hif_ind_suspend_resume_tx *arg) { if (arg->suspend_resume_flags.bc_mc_only) { bool cancel_tmo = false; diff --git a/drivers/staging/wfx/sta.h b/drivers/staging/wfx/sta.h index 4ccf1b17632b..721b7cee9c10 100644 --- a/drivers/staging/wfx/sta.h +++ b/drivers/staging/wfx/sta.h @@ -92,7 +92,7 @@ void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw, // WSM Callbacks void wfx_suspend_resume(struct wfx_vif *wvif, - struct hif_ind_suspend_resume_tx *arg); + const struct hif_ind_suspend_resume_tx *arg); // Other Helpers void wfx_cqm_bssloss_sm(struct wfx_vif *wvif, int init, int good, int bad); From aedeb963c956ef2298aa2dee62ca2049e307e7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:00 +0000 Subject: [PATCH 123/353] staging: wfx: fix typo in "num_of_ssi_ds" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The script that has imported API headers has made a mistake in "num_of_ssi_ds". Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-24-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_api_cmd.h | 4 ++-- drivers/staging/wfx/hif_tx.c | 10 +++++----- drivers/staging/wfx/scan.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/wfx/hif_api_cmd.h b/drivers/staging/wfx/hif_api_cmd.h index c15831de4ff4..90ba6e9b82ea 100644 --- a/drivers/staging/wfx/hif_api_cmd.h +++ b/drivers/staging/wfx/hif_api_cmd.h @@ -180,7 +180,7 @@ struct hif_req_start_scan { struct hif_auto_scan_param auto_scan_param; u8 num_of_probe_requests; u8 probe_delay; - u8 num_of_ssi_ds; + u8 num_of_ssids; u8 num_of_channels; u32 min_channel_time; u32 max_channel_time; @@ -196,7 +196,7 @@ struct hif_start_scan_req_cstnbssid_body { struct hif_auto_scan_param auto_scan_param; u8 num_of_probe_requests; u8 probe_delay; - u8 num_of_ssi_ds; + u8 num_of_ssids; u8 num_of_channels; u32 min_channel_time; u32 max_channel_time; diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index e8c2bd1efbac..2f74abca2b60 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -227,12 +227,12 @@ int hif_scan(struct wfx_vif *wvif, const struct wfx_scan_params *arg) struct hif_ssid_def *ssids; size_t buf_len = sizeof(struct hif_req_start_scan) + arg->scan_req.num_of_channels * sizeof(u8) + - arg->scan_req.num_of_ssi_ds * sizeof(struct hif_ssid_def); + arg->scan_req.num_of_ssids * sizeof(struct hif_ssid_def); struct hif_req_start_scan *body = wfx_alloc_hif(buf_len, &hif); u8 *ptr = (u8 *) body + sizeof(*body); WARN(arg->scan_req.num_of_channels > HIF_API_MAX_NB_CHANNELS, "invalid params"); - WARN(arg->scan_req.num_of_ssi_ds > 2, "invalid params"); + WARN(arg->scan_req.num_of_ssids > 2, "invalid params"); WARN(arg->scan_req.band > 1, "invalid params"); // FIXME: This API is unnecessary complex, fixing NumOfChannels and @@ -243,11 +243,11 @@ int hif_scan(struct wfx_vif *wvif, const struct wfx_scan_params *arg) cpu_to_le32s(&body->max_channel_time); cpu_to_le32s(&body->tx_power_level); memcpy(ptr, arg->ssids, - arg->scan_req.num_of_ssi_ds * sizeof(struct hif_ssid_def)); + arg->scan_req.num_of_ssids * sizeof(struct hif_ssid_def)); ssids = (struct hif_ssid_def *) ptr; - for (i = 0; i < body->num_of_ssi_ds; ++i) + for (i = 0; i < body->num_of_ssids; ++i) cpu_to_le32s(&ssids[i].ssid_length); - ptr += arg->scan_req.num_of_ssi_ds * sizeof(struct hif_ssid_def); + ptr += arg->scan_req.num_of_ssids * sizeof(struct hif_ssid_def); memcpy(ptr, arg->ch, arg->scan_req.num_of_channels * sizeof(u8)); ptr += arg->scan_req.num_of_channels * sizeof(u8); WARN(buf_len != ptr - (u8 *) body, "allocation size mismatch"); diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index 45e78c5722ff..cb7a1fdd0001 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -204,7 +204,7 @@ void wfx_scan_work(struct work_struct *work) scan.scan_req.max_transmit_rate = API_RATE_INDEX_B_1MBPS; scan.scan_req.num_of_probe_requests = (first->flags & IEEE80211_CHAN_NO_IR) ? 0 : 2; - scan.scan_req.num_of_ssi_ds = wvif->scan.n_ssids; + scan.scan_req.num_of_ssids = wvif->scan.n_ssids; scan.ssids = &wvif->scan.ssids[0]; scan.scan_req.num_of_channels = it - wvif->scan.curr; scan.scan_req.probe_delay = 100; From 8a222e03997a6c660e8393231bf6811ed2066178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:01 +0000 Subject: [PATCH 124/353] staging: wfx: fix typo in "num_i_es" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The script that has imported API header has made a mistake "num_i_es". Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-25-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_api_cmd.h | 2 +- drivers/staging/wfx/hif_tx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wfx/hif_api_cmd.h b/drivers/staging/wfx/hif_api_cmd.h index 90ba6e9b82ea..3e77fbe3d5ff 100644 --- a/drivers/staging/wfx/hif_api_cmd.h +++ b/drivers/staging/wfx/hif_api_cmd.h @@ -137,7 +137,7 @@ struct hif_ie_tlv { struct hif_req_update_ie { struct hif_ie_flags ie_flags; - u16 num_i_es; + u16 num_ies; struct hif_ie_tlv ie[]; } __packed; diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index 2f74abca2b60..6fb98ddbc0e2 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -429,7 +429,7 @@ int hif_update_ie(struct wfx_vif *wvif, const struct hif_ie_flags *target_frame, struct hif_req_update_ie *body = wfx_alloc_hif(buf_len, &hif); memcpy(&body->ie_flags, target_frame, sizeof(struct hif_ie_flags)); - body->num_i_es = cpu_to_le16(1); + body->num_ies = cpu_to_le16(1); memcpy(body->ie, ies, ies_len); wfx_fill_header(hif, wvif->id, HIF_REQ_ID_UPDATE_IE, buf_len); ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); From 48f3ab9d8d4e2f3dab45a43ef48eb6adbe7ee99a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:03 +0000 Subject: [PATCH 125/353] staging: wfx: fix name of struct hif_req_start_scan_alt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original name did not make any sense. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-26-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_api_cmd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wfx/hif_api_cmd.h b/drivers/staging/wfx/hif_api_cmd.h index 3e77fbe3d5ff..4ce3bb51cf04 100644 --- a/drivers/staging/wfx/hif_api_cmd.h +++ b/drivers/staging/wfx/hif_api_cmd.h @@ -188,7 +188,7 @@ struct hif_req_start_scan { u8 ssid_and_channel_lists[]; } __packed; -struct hif_start_scan_req_cstnbssid_body { +struct hif_req_start_scan_alt { u8 band; struct hif_scan_type scan_type; struct hif_scan_flags scan_flags; From c2232d94ac67dc0a76656e8e15ae38a21d326eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:04 +0000 Subject: [PATCH 126/353] staging: wfx: improve API of hif_req_join->infrastructure_bss_mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In fact "mode" is a boolean that indicates if IBSS mode is used. This patch fixes the name and uses a more adapted memory representation. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-27-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_api_cmd.h | 8 ++------ drivers/staging/wfx/sta.c | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wfx/hif_api_cmd.h b/drivers/staging/wfx/hif_api_cmd.h index 4ce3bb51cf04..e848bd3073a2 100644 --- a/drivers/staging/wfx/hif_api_cmd.h +++ b/drivers/staging/wfx/hif_api_cmd.h @@ -377,11 +377,6 @@ struct hif_cnf_edca_queue_params { u32 status; } __packed; -enum hif_ap_mode { - HIF_MODE_IBSS = 0x0, - HIF_MODE_BSS = 0x1 -}; - enum hif_preamble { HIF_PREAMBLE_LONG = 0x0, HIF_PREAMBLE_SHORT = 0x1, @@ -396,7 +391,8 @@ struct hif_join_flags { } __packed; struct hif_req_join { - u8 mode; + u8 infrastructure_bss_mode:1; + u8 reserved1:7; u8 band; u16 channel_number; u8 bssid[ETH_ALEN]; diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index b4bb5b653e64..23ec7a4a926b 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -651,7 +651,7 @@ static void wfx_do_join(struct wfx_vif *wvif) struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf; struct cfg80211_bss *bss = NULL; struct hif_req_join join = { - .mode = conf->ibss_joined ? HIF_MODE_IBSS : HIF_MODE_BSS, + .infrastructure_bss_mode = !conf->ibss_joined, .preamble_type = conf->use_short_preamble ? HIF_PREAMBLE_SHORT : HIF_PREAMBLE_LONG, .probe_for_join = 1, .atim_window = 0, From ad636ec4f01a06a59433d126c5754127b3157197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:05 +0000 Subject: [PATCH 127/353] staging: wfx: better naming for hif_req_join->short_preamble MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HIF_PREAMBLE_SHORT_LONG12 is never used. So it is possible to change "preamble_type" into a boolean and drop "enum hif_preamble". Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-28-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_api_cmd.h | 16 ++++++---------- drivers/staging/wfx/hif_api_mib.h | 5 +++-- drivers/staging/wfx/sta.c | 6 +++--- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/staging/wfx/hif_api_cmd.h b/drivers/staging/wfx/hif_api_cmd.h index e848bd3073a2..fc078d54bfbf 100644 --- a/drivers/staging/wfx/hif_api_cmd.h +++ b/drivers/staging/wfx/hif_api_cmd.h @@ -377,12 +377,6 @@ struct hif_cnf_edca_queue_params { u32 status; } __packed; -enum hif_preamble { - HIF_PREAMBLE_LONG = 0x0, - HIF_PREAMBLE_SHORT = 0x1, - HIF_PREAMBLE_SHORT_LONG12 = 0x2 -}; - struct hif_join_flags { u8 reserved1:2; u8 force_no_beacon:1; @@ -397,9 +391,10 @@ struct hif_req_join { u16 channel_number; u8 bssid[ETH_ALEN]; u16 atim_window; - u8 preamble_type; + u8 short_preamble:1; + u8 reserved2:7; u8 probe_for_join; - u8 reserved; + u8 reserved3; struct hif_join_flags join_flags; u32 ssid_length; u8 ssid[HIF_API_SSID_SIZE]; @@ -462,8 +457,9 @@ struct hif_req_start { u32 reserved1; u32 beacon_interval; u8 dtim_period; - u8 preamble_type; - u8 reserved2; + u8 short_preamble:1; + u8 reserved2:7; + u8 reserved3; u8 ssid_length; u8 ssid[HIF_API_SSID_SIZE]; u32 basic_rate_set; diff --git a/drivers/staging/wfx/hif_api_mib.h b/drivers/staging/wfx/hif_api_mib.h index 94b789ceb4ff..34e4310ad71f 100644 --- a/drivers/staging/wfx/hif_api_mib.h +++ b/drivers/staging/wfx/hif_api_mib.h @@ -471,8 +471,9 @@ struct hif_mib_set_association_mode { u8 mode:1; u8 rateset:1; u8 spacing:1; - u8 reserved:4; - u8 preamble_type; + u8 reserved1:4; + u8 short_preamble:1; + u8 reserved2:7; u8 mixed_or_greenfield_type; u8 mpdu_start_spacing; u32 basic_rate_set; diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 23ec7a4a926b..e5c933678c47 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -652,7 +652,7 @@ static void wfx_do_join(struct wfx_vif *wvif) struct cfg80211_bss *bss = NULL; struct hif_req_join join = { .infrastructure_bss_mode = !conf->ibss_joined, - .preamble_type = conf->use_short_preamble ? HIF_PREAMBLE_SHORT : HIF_PREAMBLE_LONG, + .short_preamble = conf->use_short_preamble, .probe_for_join = 1, .atim_window = 0, .basic_rate_set = wfx_rate_mask_to_hw(wvif->wdev, @@ -843,7 +843,7 @@ static int wfx_start_ap(struct wfx_vif *wvif) .channel_number = wvif->channel->hw_value, .beacon_interval = conf->beacon_int, .dtim_period = conf->dtim_period, - .preamble_type = conf->use_short_preamble ? HIF_PREAMBLE_SHORT : HIF_PREAMBLE_LONG, + .short_preamble = conf->use_short_preamble, .basic_rate_set = wfx_rate_mask_to_hw(wvif->wdev, conf->basic_rates), }; @@ -994,7 +994,7 @@ static void wfx_join_finalize(struct wfx_vif *wvif, association_mode.mode = 1; association_mode.rateset = 1; association_mode.spacing = 1; - association_mode.preamble_type = info->use_short_preamble ? HIF_PREAMBLE_SHORT : HIF_PREAMBLE_LONG; + association_mode.short_preamble = info->use_short_preamble; association_mode.basic_rate_set = cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, info->basic_rates)); association_mode.mixed_or_greenfield_type = wfx_ht_greenfield(&wvif->ht_info); association_mode.mpdu_start_spacing = wfx_ht_ampdu_density(&wvif->ht_info); From 07c11c18ebb50c4f4b3fb5a40cbce212352b35bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:07 +0000 Subject: [PATCH 128/353] staging: wfx: better naming for hif_mib_set_association_mode->greenfield MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current name "mixed_or_greenfield_type" does not allow to know if "true" means "mixed" of "greenfield". It is possible to use a better name and drop "enum hif_tx_mode". Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-29-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_api_mib.h | 8 ++------ drivers/staging/wfx/sta.c | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wfx/hif_api_mib.h b/drivers/staging/wfx/hif_api_mib.h index 34e4310ad71f..1603b3074bf7 100644 --- a/drivers/staging/wfx/hif_api_mib.h +++ b/drivers/staging/wfx/hif_api_mib.h @@ -395,11 +395,6 @@ struct hif_mib_non_erp_protection { u8 reserved2[3]; } __packed; -enum hif_tx_mode { - HIF_TX_MODE_MIXED = 0x0, - HIF_TX_MODE_GREENFIELD = 0x1 -}; - enum hif_tmplt { HIF_TMPLT_PRBREQ = 0x0, HIF_TMPLT_BCN = 0x1, @@ -474,7 +469,8 @@ struct hif_mib_set_association_mode { u8 reserved1:4; u8 short_preamble:1; u8 reserved2:7; - u8 mixed_or_greenfield_type; + u8 greenfield:1; + u8 reserved3:7; u8 mpdu_start_spacing; u32 basic_rate_set; } __packed; diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index e5c933678c47..939c64f108ed 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -996,7 +996,7 @@ static void wfx_join_finalize(struct wfx_vif *wvif, association_mode.spacing = 1; association_mode.short_preamble = info->use_short_preamble; association_mode.basic_rate_set = cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, info->basic_rates)); - association_mode.mixed_or_greenfield_type = wfx_ht_greenfield(&wvif->ht_info); + association_mode.greenfield = wfx_ht_greenfield(&wvif->ht_info); association_mode.mpdu_start_spacing = wfx_ht_ampdu_density(&wvif->ht_info); wfx_cqm_bssloss_sm(wvif, 0, 0, 0); From 536607c0c793540ee53b2242d4f676e0898f9e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:08 +0000 Subject: [PATCH 129/353] staging: wfx: simplify handling of tx_lock in wfx_do_join() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the old days, wfx_do_join() could be called from different contexts. Now that wfx_do_join() is called only from one place, it is cleaner to keep lock and unlock of data inside the function. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-30-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 939c64f108ed..62e65493a4fe 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -644,7 +644,6 @@ static void wfx_set_mfp(struct wfx_vif *wvif, hif_set_mfp(wvif, mfpc, mfpr); } -/* MUST be called with tx_lock held! It will be unlocked for us. */ static void wfx_do_join(struct wfx_vif *wvif) { const u8 *bssid; @@ -659,6 +658,8 @@ static void wfx_do_join(struct wfx_vif *wvif) conf->basic_rates), }; + wfx_tx_lock_flush(wvif->wdev); + if (wvif->channel->flags & IEEE80211_CHAN_NO_IR) join.probe_for_join = 0; @@ -1180,10 +1181,8 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, } mutex_unlock(&wdev->conf_mutex); - if (do_join) { - wfx_tx_lock_flush(wdev); - wfx_do_join(wvif); /* Will unlock it for us */ - } + if (do_join) + wfx_do_join(wvif); } static void wfx_ps_notify(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd, From 155665d87e08814d6e47277be2e706534497c638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:09 +0000 Subject: [PATCH 130/353] staging: wfx: firmware already handle powersave mode during scan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When user try to launch scan while connected, it is necessary to notify the AP that we cannot receive data (using power save mode). Firmware already handles this automatically so the code in the driver is redundant and can be dropped. By edge effect, hack of scan status in wfx_set_pm() is now useless. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-31-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/scan.c | 14 -------------- drivers/staging/wfx/sta.c | 7 +------ 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index cb7a1fdd0001..4b95e6a97df7 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -141,22 +141,11 @@ void wfx_scan_work(struct work_struct *work) .scan_req.scan_type.type = 0, /* Foreground */ }; struct ieee80211_channel *first; - bool first_run = (wvif->scan.begin == wvif->scan.curr && - wvif->scan.begin != wvif->scan.end); int i; down(&wvif->scan.lock); mutex_lock(&wvif->wdev->conf_mutex); - if (first_run) { - if (wvif->state == WFX_STATE_STA && - !(wvif->powersave_mode.pm_mode.enter_psm)) { - struct hif_req_set_pm_mode pm = wvif->powersave_mode; - - pm.pm_mode.enter_psm = 1; - wfx_set_pm(wvif, &pm); - } - } if (!wvif->scan.req || wvif->scan.curr == wvif->scan.end) { if (wvif->scan.output_power != wvif->wdev->output_power) @@ -177,9 +166,6 @@ void wfx_scan_work(struct work_struct *work) __ieee80211_scan_completed_compat(wvif->wdev->hw, wvif->scan.status ? 1 : 0); up(&wvif->scan.lock); - if (wvif->state == WFX_STATE_STA && - !(wvif->powersave_mode.pm_mode.enter_psm)) - wfx_set_pm(wvif, &wvif->powersave_mode); return; } first = *wvif->scan.curr; diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 62e65493a4fe..fb45aa66fc56 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -375,7 +375,6 @@ int wfx_set_pm(struct wfx_vif *wvif, const struct hif_req_set_pm_mode *arg) { struct hif_req_set_pm_mode pm = *arg; u16 uapsd_flags; - int ret; if (wvif->state != WFX_STATE_STA || !wvif->bss_params.aid) return 0; @@ -396,11 +395,7 @@ int wfx_set_pm(struct wfx_vif *wvif, const struct hif_req_set_pm_mode *arg) msecs_to_jiffies(300))) dev_warn(wvif->wdev->dev, "timeout while waiting of set_pm_mode_complete\n"); - ret = hif_set_pm(wvif, &pm); - // FIXME: why ? - if (-ETIMEDOUT == wvif->scan.status) - wvif->scan.status = 1; - return ret; + return hif_set_pm(wvif, &pm); } int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) From 97e587bd08939f8b0e315bd1be4beccaf296179d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:11 +0000 Subject: [PATCH 131/353] staging: wfx: declare wfx_set_pm() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wfx_set_pm() is now only used by sta.c. It can be declared static. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-32-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 57 ++++++++++++++++++++------------------- drivers/staging/wfx/sta.h | 1 - 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index fb45aa66fc56..eb087b9c8097 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -326,6 +326,36 @@ void wfx_configure_filter(struct ieee80211_hw *hw, } } +static int wfx_set_pm(struct wfx_vif *wvif, + const struct hif_req_set_pm_mode *arg) +{ + struct hif_req_set_pm_mode pm = *arg; + u16 uapsd_flags; + int ret; + + if (wvif->state != WFX_STATE_STA || !wvif->bss_params.aid) + return 0; + + memcpy(&uapsd_flags, &wvif->uapsd_info, sizeof(uapsd_flags)); + + if (uapsd_flags != 0) + pm.pm_mode.fast_psm = 0; + + // Kernel disable PowerSave when multiple vifs are in use. In contrary, + // it is absolutly necessary to enable PowerSave for WF200 + // FIXME: only if channel vif0 != channel vif1 + if (wvif_count(wvif->wdev) > 1) { + pm.pm_mode.enter_psm = 1; + pm.pm_mode.fast_psm = 0; + } + + if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete, + msecs_to_jiffies(300))) + dev_warn(wvif->wdev->dev, + "timeout while waiting of set_pm_mode_complete\n"); + return hif_set_pm(wvif, &pm); +} + int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params) { @@ -371,33 +401,6 @@ out: return ret; } -int wfx_set_pm(struct wfx_vif *wvif, const struct hif_req_set_pm_mode *arg) -{ - struct hif_req_set_pm_mode pm = *arg; - u16 uapsd_flags; - - if (wvif->state != WFX_STATE_STA || !wvif->bss_params.aid) - return 0; - - memcpy(&uapsd_flags, &wvif->uapsd_info, sizeof(uapsd_flags)); - - if (uapsd_flags != 0) - pm.pm_mode.fast_psm = 0; - - // Kernel disable PowerSave when multiple vifs are in use. In contrary, - // it is absolutly necessary to enable PowerSave for WF200 - if (wvif_count(wvif->wdev) > 1) { - pm.pm_mode.enter_psm = 1; - pm.pm_mode.fast_psm = 0; - } - - if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete, - msecs_to_jiffies(300))) - dev_warn(wvif->wdev->dev, - "timeout while waiting of set_pm_mode_complete\n"); - return hif_set_pm(wvif, &pm); -} - int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) { struct wfx_dev *wdev = hw->priv; diff --git a/drivers/staging/wfx/sta.h b/drivers/staging/wfx/sta.h index 721b7cee9c10..4719807bc25a 100644 --- a/drivers/staging/wfx/sta.h +++ b/drivers/staging/wfx/sta.h @@ -97,7 +97,6 @@ void wfx_suspend_resume(struct wfx_vif *wvif, // Other Helpers void wfx_cqm_bssloss_sm(struct wfx_vif *wvif, int init, int good, int bad); void wfx_update_filtering(struct wfx_vif *wvif); -int wfx_set_pm(struct wfx_vif *wvif, const struct hif_req_set_pm_mode *arg); int wfx_fwd_probe_req(struct wfx_vif *wvif, bool enable); #endif /* WFX_STA_H */ From 8dd5bb6631949f78c8aff1747f496265a97b1375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:12 +0000 Subject: [PATCH 132/353] staging: wfx: drop useless argument from wfx_set_pm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Argument to wfx_set_pm() is always wvif->powersave_mode. So, we can simplify it. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-33-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index eb087b9c8097..ee1b15950389 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -326,12 +326,10 @@ void wfx_configure_filter(struct ieee80211_hw *hw, } } -static int wfx_set_pm(struct wfx_vif *wvif, - const struct hif_req_set_pm_mode *arg) +static int wfx_update_pm(struct wfx_vif *wvif) { - struct hif_req_set_pm_mode pm = *arg; + struct hif_req_set_pm_mode pm = wvif->powersave_mode; u16 uapsd_flags; - int ret; if (wvif->state != WFX_STATE_STA || !wvif->bss_params.aid) return 0; @@ -390,7 +388,7 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (!ret && wvif->setbssparams_done && wvif->state == WFX_STATE_STA && old_uapsd_flags != new_uapsd_flags) - ret = wfx_set_pm(wvif, &wvif->powersave_mode); + ret = wfx_update_pm(wvif); } } else { ret = -EINVAL; @@ -1014,7 +1012,7 @@ static void wfx_join_finalize(struct wfx_vif *wvif, hif_set_bss_params(wvif, &wvif->bss_params); wvif->setbssparams_done = true; wfx_set_beacon_wakeup_period_work(&wvif->set_beacon_wakeup_period_work); - wfx_set_pm(wvif, &wvif->powersave_mode); + wfx_update_pm(wvif); } } @@ -1451,7 +1449,7 @@ int wfx_config(struct ieee80211_hw *hw, u32 changed) } } if (wvif->state == WFX_STATE_STA && wvif->bss_params.aid) - wfx_set_pm(wvif, &wvif->powersave_mode); + wfx_update_pm(wvif); } wvif = wdev_to_wvif(wdev, 0); } @@ -1591,7 +1589,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) else hif_set_block_ack_policy(wvif, 0x00, 0x00); // Combo force powersave mode. We can re-enable it now - wfx_set_pm(wvif, &wvif->powersave_mode); + wfx_update_pm(wvif); } return 0; } @@ -1666,7 +1664,7 @@ void wfx_remove_interface(struct ieee80211_hw *hw, else hif_set_block_ack_policy(wvif, 0x00, 0x00); // Combo force powersave mode. We can re-enable it now - wfx_set_pm(wvif, &wvif->powersave_mode); + wfx_update_pm(wvif); } } From ad41f7196bd3eafa2e879ec7f3d387a49666f677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:13 +0000 Subject: [PATCH 133/353] staging: wfx: remove redundant test while calling wfx_update_pm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Condition about wvif->state and wvif->bss_params.aid is already checked at beginning of wfx_update_pm(). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-34-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index ee1b15950389..91fa4d8aa37d 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -1448,8 +1448,7 @@ int wfx_config(struct ieee80211_hw *hw, u32 changed) 2, 255); } } - if (wvif->state == WFX_STATE_STA && wvif->bss_params.aid) - wfx_update_pm(wvif); + wfx_update_pm(wvif); } wvif = wdev_to_wvif(wdev, 0); } From 50ad848cc6d6c6290a38b62ea60abefb903396d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:15 +0000 Subject: [PATCH 134/353] staging: wfx: drop unnecessary wvif->powersave_mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Power save status is already available in bss_conf. So there is no reason to keep information duplicated in wvif->powersave_mode. In add, type of wvif->powersave_mode is low level struct made to communicate with device. We would like to limit usage of this kind of struct in upper layers of the driver. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-35-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 31 +++++++++++++------------------ drivers/staging/wfx/wfx.h | 1 - 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 91fa4d8aa37d..c57135f77572 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -328,12 +328,23 @@ void wfx_configure_filter(struct ieee80211_hw *hw, static int wfx_update_pm(struct wfx_vif *wvif) { - struct hif_req_set_pm_mode pm = wvif->powersave_mode; + struct ieee80211_conf *conf = &wvif->wdev->hw->conf; + struct hif_req_set_pm_mode pm; u16 uapsd_flags; if (wvif->state != WFX_STATE_STA || !wvif->bss_params.aid) return 0; + memset(&pm, 0, sizeof(pm)); + if (conf->flags & IEEE80211_CONF_PS) { + pm.pm_mode.enter_psm = 1; + // Firmware does not support more than 128ms + pm.fast_psm_idle_period = + min(conf->dynamic_ps_timeout * 2, 255); + if (pm.fast_psm_idle_period) + pm.pm_mode.fast_psm = 1; + } + memcpy(&uapsd_flags, &wvif->uapsd_info, sizeof(uapsd_flags)); if (uapsd_flags != 0) @@ -1432,24 +1443,8 @@ int wfx_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_PS) { wvif = NULL; - while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { - memset(&wvif->powersave_mode, 0, - sizeof(wvif->powersave_mode)); - if (conf->flags & IEEE80211_CONF_PS) { - wvif->powersave_mode.pm_mode.enter_psm = 1; - if (conf->dynamic_ps_timeout > 0) { - wvif->powersave_mode.pm_mode.fast_psm = 1; - /* - * Firmware does not support more than - * 128ms - */ - wvif->powersave_mode.fast_psm_idle_period = - min(conf->dynamic_ps_timeout * - 2, 255); - } - } + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) wfx_update_pm(wvif); - } wvif = wdev_to_wvif(wdev, 0); } diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 781a8c8ba982..c82d29764d66 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -125,7 +125,6 @@ struct wfx_vif { struct wfx_scan scan; - struct hif_req_set_pm_mode powersave_mode; struct completion set_pm_mode_complete; struct list_head event_queue; From 3f97c37063bca3948cbb8a2275f34dba7e86d025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:16 +0000 Subject: [PATCH 135/353] staging: wfx: do not try to save call to hif_set_pm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current code try to not exchange data with device if it is not necessary. However, it seems that the additional code does not provide any gain. So, we prefer to keep a simpler code. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-36-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index c57135f77572..dcb4693ec980 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -371,14 +371,11 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; int ret = 0; - /* To prevent re-applying PM request OID again and again*/ - u16 old_uapsd_flags, new_uapsd_flags; struct hif_req_edca_queue_params *edca; mutex_lock(&wdev->conf_mutex); if (queue < hw->queues) { - old_uapsd_flags = *((u16 *) &wvif->uapsd_info); edca = &wvif->edca.params[queue]; wvif->edca.uapsd_enable[queue] = params->uapsd; @@ -395,10 +392,8 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (wvif->vif->type == NL80211_IFTYPE_STATION) { ret = wfx_set_uapsd_param(wvif, &wvif->edca); - new_uapsd_flags = *((u16 *) &wvif->uapsd_info); if (!ret && wvif->setbssparams_done && - wvif->state == WFX_STATE_STA && - old_uapsd_flags != new_uapsd_flags) + wvif->state == WFX_STATE_STA) ret = wfx_update_pm(wvif); } } else { From 8a274dfb59209d0e0bd96f3a7917aceba39b0ca4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:17 +0000 Subject: [PATCH 136/353] staging: wfx: fix pm_mode timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maximum request time (how long a request wait for the medium) is set in firmware to 512TU Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-37-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index dcb4693ec980..42b0d01d85cc 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -359,7 +359,7 @@ static int wfx_update_pm(struct wfx_vif *wvif) } if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete, - msecs_to_jiffies(300))) + TU_TO_JIFFIES(512))) dev_warn(wvif->wdev->dev, "timeout while waiting of set_pm_mode_complete\n"); return hif_set_pm(wvif, &pm); From c91ba8c8514307c3c60dc2b1015d379b1d01c809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:19 +0000 Subject: [PATCH 137/353] staging: wfx: simplify wfx_conf_tx() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Error management of wfx_conf_tx() can be simplified. In add, the hardware command "hif_set_edca_queue_params" never returns any error. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-38-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 42 ++++++++++++++------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 42b0d01d85cc..045d3916ada8 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -370,39 +370,27 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; - int ret = 0; struct hif_req_edca_queue_params *edca; + WARN_ON(queue >= hw->queues); + mutex_lock(&wdev->conf_mutex); + wvif->edca.uapsd_enable[queue] = params->uapsd; + edca = &wvif->edca.params[queue]; + edca->aifsn = params->aifs; + edca->cw_min = params->cw_min; + edca->cw_max = params->cw_max; + edca->tx_op_limit = params->txop * TXOP_UNIT; + edca->allowed_medium_time = 0; + hif_set_edca_queue_params(wvif, edca); - if (queue < hw->queues) { - edca = &wvif->edca.params[queue]; - - wvif->edca.uapsd_enable[queue] = params->uapsd; - edca->aifsn = params->aifs; - edca->cw_min = params->cw_min; - edca->cw_max = params->cw_max; - edca->tx_op_limit = params->txop * TXOP_UNIT; - edca->allowed_medium_time = 0; - ret = hif_set_edca_queue_params(wvif, edca); - if (ret) { - ret = -EINVAL; - goto out; - } - - if (wvif->vif->type == NL80211_IFTYPE_STATION) { - ret = wfx_set_uapsd_param(wvif, &wvif->edca); - if (!ret && wvif->setbssparams_done && - wvif->state == WFX_STATE_STA) - ret = wfx_update_pm(wvif); - } - } else { - ret = -EINVAL; + if (wvif->vif->type == NL80211_IFTYPE_STATION) { + wfx_set_uapsd_param(wvif, &wvif->edca); + if (wvif->setbssparams_done && wvif->state == WFX_STATE_STA) + wfx_update_pm(wvif); } - -out: mutex_unlock(&wdev->conf_mutex); - return ret; + return 0; } int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) From 010149e6fbccc48d726afb8e68cdc30c8b703c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:20 +0000 Subject: [PATCH 138/353] staging: wfx: prefer a bitmask instead of an array of boolean MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is easier to manipulate a int than an array of booleans. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-39-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 17 +++++++---------- drivers/staging/wfx/sta.h | 2 +- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 045d3916ada8..e59560f499ea 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -119,22 +119,22 @@ static int wfx_set_uapsd_param(struct wfx_vif *wvif, * VO [0,3], VI [1, 2], BE [2, 1], BK [3, 0] */ - if (arg->uapsd_enable[IEEE80211_AC_VO]) + if (arg->uapsd_mask & BIT(IEEE80211_AC_VO)) wvif->uapsd_info.trig_voice = 1; else wvif->uapsd_info.trig_voice = 0; - if (arg->uapsd_enable[IEEE80211_AC_VI]) + if (arg->uapsd_mask & BIT(IEEE80211_AC_VI)) wvif->uapsd_info.trig_video = 1; else wvif->uapsd_info.trig_video = 0; - if (arg->uapsd_enable[IEEE80211_AC_BE]) + if (arg->uapsd_mask & BIT(IEEE80211_AC_BE)) wvif->uapsd_info.trig_be = 1; else wvif->uapsd_info.trig_be = 0; - if (arg->uapsd_enable[IEEE80211_AC_BK]) + if (arg->uapsd_mask & BIT(IEEE80211_AC_BK)) wvif->uapsd_info.trig_bckgrnd = 1; else wvif->uapsd_info.trig_bckgrnd = 0; @@ -330,7 +330,6 @@ static int wfx_update_pm(struct wfx_vif *wvif) { struct ieee80211_conf *conf = &wvif->wdev->hw->conf; struct hif_req_set_pm_mode pm; - u16 uapsd_flags; if (wvif->state != WFX_STATE_STA || !wvif->bss_params.aid) return 0; @@ -345,9 +344,7 @@ static int wfx_update_pm(struct wfx_vif *wvif) pm.pm_mode.fast_psm = 1; } - memcpy(&uapsd_flags, &wvif->uapsd_info, sizeof(uapsd_flags)); - - if (uapsd_flags != 0) + if (wvif->edca.uapsd_mask) pm.pm_mode.fast_psm = 0; // Kernel disable PowerSave when multiple vifs are in use. In contrary, @@ -375,7 +372,7 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, WARN_ON(queue >= hw->queues); mutex_lock(&wdev->conf_mutex); - wvif->edca.uapsd_enable[queue] = params->uapsd; + assign_bit(queue, &wvif->edca.uapsd_mask, params->uapsd); edca = &wvif->edca.params[queue]; edca->aifsn = params->aifs; edca->cw_min = params->cw_min; @@ -1552,9 +1549,9 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) for (i = 0; i < IEEE80211_NUM_ACS; i++) { memcpy(&wvif->edca.params[i], &default_edca_params[i], sizeof(default_edca_params[i])); - wvif->edca.uapsd_enable[i] = false; hif_set_edca_queue_params(wvif, &wvif->edca.params[i]); } + wvif->edca.uapsd_mask = 0; wfx_set_uapsd_param(wvif, &wvif->edca); wfx_tx_policy_init(wvif); diff --git a/drivers/staging/wfx/sta.h b/drivers/staging/wfx/sta.h index 4719807bc25a..74755f6fa030 100644 --- a/drivers/staging/wfx/sta.h +++ b/drivers/staging/wfx/sta.h @@ -37,7 +37,7 @@ struct wfx_hif_event { struct wfx_edca_params { /* NOTE: index is a linux queue id. */ struct hif_req_edca_queue_params params[IEEE80211_NUM_ACS]; - bool uapsd_enable[IEEE80211_NUM_ACS]; + unsigned long uapsd_mask; }; struct wfx_grp_addr_table { From d74d60c3a1784b6333cdfbf919316d353c934352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:21 +0000 Subject: [PATCH 139/353] staging: wfx: simplify hif_set_uapsd_info() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is useless to keep uapsd_info in struct wfx_vif. This structure can be rebuilt just before to be sent. In add, the struct hif_mib_set_uapsd_information comes from hardware API. It is not intended to be manipulated in upper layers of the driver. So, this patch relocates the handling of this struct to hif_set_uapsd_info() (the low level function). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-40-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx_mib.h | 15 +++++++++--- drivers/staging/wfx/sta.c | 42 ++------------------------------ drivers/staging/wfx/wfx.h | 1 - 3 files changed, 14 insertions(+), 44 deletions(-) diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index 9be74881c56c..d77765f75f10 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -238,12 +238,21 @@ static inline int hif_use_multi_tx_conf(struct wfx_dev *wdev, &arg, sizeof(arg)); } -static inline int hif_set_uapsd_info(struct wfx_vif *wvif, - struct hif_mib_set_uapsd_information *arg) +static inline int hif_set_uapsd_info(struct wfx_vif *wvif, unsigned long val) { + struct hif_mib_set_uapsd_information arg = { }; + + if (val & BIT(IEEE80211_AC_VO)) + arg.trig_voice = 1; + if (val & BIT(IEEE80211_AC_VI)) + arg.trig_video = 1; + if (val & BIT(IEEE80211_AC_BE)) + arg.trig_be = 1; + if (val & BIT(IEEE80211_AC_BK)) + arg.trig_bckgrnd = 1; return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_SET_UAPSD_INFORMATION, - arg, sizeof(*arg)); + &arg, sizeof(arg)); } static inline int hif_erp_use_protection(struct wfx_vif *wvif, bool enable) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index e59560f499ea..9eca35d91ad3 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -112,44 +112,6 @@ end: mutex_unlock(&wvif->bss_loss_lock); } -static int wfx_set_uapsd_param(struct wfx_vif *wvif, - const struct wfx_edca_params *arg) -{ - /* Here's the mapping AC [queue, bit] - * VO [0,3], VI [1, 2], BE [2, 1], BK [3, 0] - */ - - if (arg->uapsd_mask & BIT(IEEE80211_AC_VO)) - wvif->uapsd_info.trig_voice = 1; - else - wvif->uapsd_info.trig_voice = 0; - - if (arg->uapsd_mask & BIT(IEEE80211_AC_VI)) - wvif->uapsd_info.trig_video = 1; - else - wvif->uapsd_info.trig_video = 0; - - if (arg->uapsd_mask & BIT(IEEE80211_AC_BE)) - wvif->uapsd_info.trig_be = 1; - else - wvif->uapsd_info.trig_be = 0; - - if (arg->uapsd_mask & BIT(IEEE80211_AC_BK)) - wvif->uapsd_info.trig_bckgrnd = 1; - else - wvif->uapsd_info.trig_bckgrnd = 0; - - /* Currently pseudo U-APSD operation is not supported, so setting - * MinAutoTriggerInterval, MaxAutoTriggerInterval and - * AutoTriggerStep to 0 - */ - wvif->uapsd_info.min_auto_trigger_interval = 0; - wvif->uapsd_info.max_auto_trigger_interval = 0; - wvif->uapsd_info.auto_trigger_step = 0; - - return hif_set_uapsd_info(wvif, &wvif->uapsd_info); -} - int wfx_fwd_probe_req(struct wfx_vif *wvif, bool enable) { wvif->fwd_probe_req = enable; @@ -382,7 +344,7 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, hif_set_edca_queue_params(wvif, edca); if (wvif->vif->type == NL80211_IFTYPE_STATION) { - wfx_set_uapsd_param(wvif, &wvif->edca); + hif_set_uapsd_info(wvif, wvif->edca.uapsd_mask); if (wvif->setbssparams_done && wvif->state == WFX_STATE_STA) wfx_update_pm(wvif); } @@ -1552,7 +1514,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) hif_set_edca_queue_params(wvif, &wvif->edca.params[i]); } wvif->edca.uapsd_mask = 0; - wfx_set_uapsd_param(wvif, &wvif->edca); + hif_set_uapsd_info(wvif, wvif->edca.uapsd_mask); wfx_tx_policy_init(wvif); wvif = NULL; diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index c82d29764d66..ff29163436b6 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -114,7 +114,6 @@ struct wfx_vif { bool setbssparams_done; struct wfx_ht_info ht_info; struct wfx_edca_params edca; - struct hif_mib_set_uapsd_information uapsd_info; struct hif_req_set_bss_params bss_params; struct work_struct bss_params_work; struct work_struct set_cts_work; From adc90758f4d508fa6a462fbc3f67821387a3e2a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:23 +0000 Subject: [PATCH 140/353] staging: wfx: simplify hif_set_pm() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct hif_req_set_pm_mode comes from hardware API. It is not intended to be manipulated in upper layers of the driver. So, this patch relocate the handling of this struct to hif_set_pm() (the low level function). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-41-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx.c | 10 ++++++++-- drivers/staging/wfx/hif_tx.h | 2 +- drivers/staging/wfx/sta.c | 25 +++++++++---------------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index 6fb98ddbc0e2..9cbf9d916f5f 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -360,13 +360,19 @@ int hif_set_edca_queue_params(struct wfx_vif *wvif, return ret; } -int hif_set_pm(struct wfx_vif *wvif, const struct hif_req_set_pm_mode *arg) +int hif_set_pm(struct wfx_vif *wvif, bool ps, int dynamic_ps_timeout) { int ret; struct hif_msg *hif; struct hif_req_set_pm_mode *body = wfx_alloc_hif(sizeof(*body), &hif); - memcpy(body, arg, sizeof(*body)); + if (ps) { + body->pm_mode.enter_psm = 1; + // Firmware does not support more than 128ms + body->fast_psm_idle_period = min(dynamic_ps_timeout * 2, 255); + if (body->fast_psm_idle_period) + body->pm_mode.fast_psm = 1; + } wfx_fill_header(hif, wvif->id, HIF_REQ_ID_SET_PM_MODE, sizeof(*body)); ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); kfree(hif); diff --git a/drivers/staging/wfx/hif_tx.h b/drivers/staging/wfx/hif_tx.h index f61ae7b0d41c..bb5860ee6542 100644 --- a/drivers/staging/wfx/hif_tx.h +++ b/drivers/staging/wfx/hif_tx.h @@ -47,7 +47,7 @@ int hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, int hif_scan(struct wfx_vif *wvif, const struct wfx_scan_params *arg); int hif_stop_scan(struct wfx_vif *wvif); int hif_join(struct wfx_vif *wvif, const struct hif_req_join *arg); -int hif_set_pm(struct wfx_vif *wvif, const struct hif_req_set_pm_mode *arg); +int hif_set_pm(struct wfx_vif *wvif, bool ps, int dynamic_ps_timeout); int hif_set_bss_params(struct wfx_vif *wvif, const struct hif_req_set_bss_params *arg); int hif_add_key(struct wfx_dev *wdev, const struct hif_req_add_key *arg); diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 9eca35d91ad3..b4007afcd0c6 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -291,37 +291,30 @@ void wfx_configure_filter(struct ieee80211_hw *hw, static int wfx_update_pm(struct wfx_vif *wvif) { struct ieee80211_conf *conf = &wvif->wdev->hw->conf; - struct hif_req_set_pm_mode pm; + bool ps = conf->flags & IEEE80211_CONF_PS; + int ps_timeout = conf->dynamic_ps_timeout; + WARN_ON(conf->dynamic_ps_timeout < 0); if (wvif->state != WFX_STATE_STA || !wvif->bss_params.aid) return 0; - - memset(&pm, 0, sizeof(pm)); - if (conf->flags & IEEE80211_CONF_PS) { - pm.pm_mode.enter_psm = 1; - // Firmware does not support more than 128ms - pm.fast_psm_idle_period = - min(conf->dynamic_ps_timeout * 2, 255); - if (pm.fast_psm_idle_period) - pm.pm_mode.fast_psm = 1; - } - + if (!ps) + ps_timeout = 0; if (wvif->edca.uapsd_mask) - pm.pm_mode.fast_psm = 0; + ps_timeout = 0; // Kernel disable PowerSave when multiple vifs are in use. In contrary, // it is absolutly necessary to enable PowerSave for WF200 // FIXME: only if channel vif0 != channel vif1 if (wvif_count(wvif->wdev) > 1) { - pm.pm_mode.enter_psm = 1; - pm.pm_mode.fast_psm = 0; + ps = true; + ps_timeout = 0; } if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete, TU_TO_JIFFIES(512))) dev_warn(wvif->wdev->dev, "timeout while waiting of set_pm_mode_complete\n"); - return hif_set_pm(wvif, &pm); + return hif_set_pm(wvif, ps, ps_timeout); } int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, From 7e2b32f54f61cc5ebc9c18d605ee84cef53eb60d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:24 +0000 Subject: [PATCH 141/353] staging: wfx: drop struct wfx_edca_params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intermediate structure wfx_edca_params does not help. This patch relocates its members directly in struct wfx_vif. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-42-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/queue.c | 4 ++-- drivers/staging/wfx/sta.c | 18 +++++++++--------- drivers/staging/wfx/sta.h | 6 ------ drivers/staging/wfx/wfx.h | 3 ++- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index 680fed31cefb..16216afe6cfc 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -452,7 +452,7 @@ static int wfx_get_prio_queue(struct wfx_vif *wvif, for (i = 0; i < IEEE80211_NUM_ACS; ++i) { int queued; - edca = &wvif->edca.params[i]; + edca = &wvif->edca_params[i]; queued = wfx_tx_queue_get_num_queued(&wvif->wdev->tx_queue[i], tx_allowed_mask); if (!queued) @@ -595,7 +595,7 @@ struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev) wvif->pspoll_mask &= ~BIT(tx_priv->raw_link_id); /* allow bursting if txop is set */ - if (wvif->edca.params[queue_num].tx_op_limit) + if (wvif->edca_params[queue_num].tx_op_limit) burst = (int)wfx_tx_queue_get_num_queued(queue, tx_allowed_mask) + 1; else burst = 1; diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index b4007afcd0c6..d52f618062a6 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -299,7 +299,7 @@ static int wfx_update_pm(struct wfx_vif *wvif) return 0; if (!ps) ps_timeout = 0; - if (wvif->edca.uapsd_mask) + if (wvif->uapsd_mask) ps_timeout = 0; // Kernel disable PowerSave when multiple vifs are in use. In contrary, @@ -327,8 +327,8 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, WARN_ON(queue >= hw->queues); mutex_lock(&wdev->conf_mutex); - assign_bit(queue, &wvif->edca.uapsd_mask, params->uapsd); - edca = &wvif->edca.params[queue]; + assign_bit(queue, &wvif->uapsd_mask, params->uapsd); + edca = &wvif->edca_params[queue]; edca->aifsn = params->aifs; edca->cw_min = params->cw_min; edca->cw_max = params->cw_max; @@ -337,7 +337,7 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, hif_set_edca_queue_params(wvif, edca); if (wvif->vif->type == NL80211_IFTYPE_STATION) { - hif_set_uapsd_info(wvif, wvif->edca.uapsd_mask); + hif_set_uapsd_info(wvif, wvif->uapsd_mask); if (wvif->setbssparams_done && wvif->state == WFX_STATE_STA) wfx_update_pm(wvif); } @@ -1426,7 +1426,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) }, }; - BUILD_BUG_ON(ARRAY_SIZE(default_edca_params) != ARRAY_SIZE(wvif->edca.params)); + BUILD_BUG_ON(ARRAY_SIZE(default_edca_params) != ARRAY_SIZE(wvif->edca_params)); if (wfx_api_older_than(wdev, 2, 0)) { default_edca_params[IEEE80211_AC_BE].queue_id = HIF_QUEUE_ID_BACKGROUND; default_edca_params[IEEE80211_AC_BK].queue_id = HIF_QUEUE_ID_BESTEFFORT; @@ -1502,12 +1502,12 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) hif_set_macaddr(wvif, vif->addr); for (i = 0; i < IEEE80211_NUM_ACS; i++) { - memcpy(&wvif->edca.params[i], &default_edca_params[i], + memcpy(&wvif->edca_params[i], &default_edca_params[i], sizeof(default_edca_params[i])); - hif_set_edca_queue_params(wvif, &wvif->edca.params[i]); + hif_set_edca_queue_params(wvif, &wvif->edca_params[i]); } - wvif->edca.uapsd_mask = 0; - hif_set_uapsd_info(wvif, wvif->edca.uapsd_mask); + wvif->uapsd_mask = 0; + hif_set_uapsd_info(wvif, wvif->uapsd_mask); wfx_tx_policy_init(wvif); wvif = NULL; diff --git a/drivers/staging/wfx/sta.h b/drivers/staging/wfx/sta.h index 74755f6fa030..9595e1fc60db 100644 --- a/drivers/staging/wfx/sta.h +++ b/drivers/staging/wfx/sta.h @@ -34,12 +34,6 @@ struct wfx_hif_event { struct hif_ind_event evt; }; -struct wfx_edca_params { - /* NOTE: index is a linux queue id. */ - struct hif_req_edca_queue_params params[IEEE80211_NUM_ACS]; - unsigned long uapsd_mask; -}; - struct wfx_grp_addr_table { bool enable; int num_addresses; diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index ff29163436b6..5a2f8af17eb7 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -113,7 +113,8 @@ struct wfx_vif { int cqm_rssi_thold; bool setbssparams_done; struct wfx_ht_info ht_info; - struct wfx_edca_params edca; + unsigned long uapsd_mask; + struct hif_req_edca_queue_params edca_params[IEEE80211_NUM_ACS]; struct hif_req_set_bss_params bss_params; struct work_struct bss_params_work; struct work_struct set_cts_work; From 654e369365fda7ed565646ccc5ac6d4f1d4dd6bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:25 +0000 Subject: [PATCH 142/353] staging: wfx: remove unnecessary EDCA initialisation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mac80211 already call wfx_conf_tx() on every VIF instanciation. So, the driver does not need to do it. Note that current code did dirty things with wvif->edca_params. This struct was initialized, but only 'queue_id' was really used. The other members are only used to store temporary values. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-43-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 51 +++++---------------------------------- 1 file changed, 6 insertions(+), 45 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index d52f618062a6..3504b6b3515e 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -334,6 +334,12 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, edca->cw_max = params->cw_max; edca->tx_op_limit = params->txop * TXOP_UNIT; edca->allowed_medium_time = 0; + edca->queue_id = 3 - queue; + // API 2.0 has changed queue IDs values + if (wfx_api_older_than(wdev, 2, 0) && queue == IEEE80211_AC_BE) + edca->queue_id = HIF_QUEUE_ID_BACKGROUND; + if (wfx_api_older_than(wdev, 2, 0) && queue == IEEE80211_AC_BK) + edca->queue_id = HIF_QUEUE_ID_BESTEFFORT; hif_set_edca_queue_params(wvif, edca); if (wvif->vif->type == NL80211_IFTYPE_STATION) { @@ -1393,44 +1399,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) int i; struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; - // FIXME: parameters are set by kernel juste after interface_add. - // Keep struct hif_req_edca_queue_params blank? - struct hif_req_edca_queue_params default_edca_params[] = { - [IEEE80211_AC_VO] = { - .queue_id = HIF_QUEUE_ID_VOICE, - .aifsn = 2, - .cw_min = 3, - .cw_max = 7, - .tx_op_limit = TXOP_UNIT * 47, - }, - [IEEE80211_AC_VI] = { - .queue_id = HIF_QUEUE_ID_VIDEO, - .aifsn = 2, - .cw_min = 7, - .cw_max = 15, - .tx_op_limit = TXOP_UNIT * 94, - }, - [IEEE80211_AC_BE] = { - .queue_id = HIF_QUEUE_ID_BESTEFFORT, - .aifsn = 3, - .cw_min = 15, - .cw_max = 1023, - .tx_op_limit = TXOP_UNIT * 0, - }, - [IEEE80211_AC_BK] = { - .queue_id = HIF_QUEUE_ID_BACKGROUND, - .aifsn = 7, - .cw_min = 15, - .cw_max = 1023, - .tx_op_limit = TXOP_UNIT * 0, - }, - }; - - BUILD_BUG_ON(ARRAY_SIZE(default_edca_params) != ARRAY_SIZE(wvif->edca_params)); - if (wfx_api_older_than(wdev, 2, 0)) { - default_edca_params[IEEE80211_AC_BE].queue_id = HIF_QUEUE_ID_BACKGROUND; - default_edca_params[IEEE80211_AC_BK].queue_id = HIF_QUEUE_ID_BESTEFFORT; - } vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | IEEE80211_VIF_SUPPORTS_UAPSD | @@ -1501,13 +1469,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mutex_unlock(&wdev->conf_mutex); hif_set_macaddr(wvif, vif->addr); - for (i = 0; i < IEEE80211_NUM_ACS; i++) { - memcpy(&wvif->edca_params[i], &default_edca_params[i], - sizeof(default_edca_params[i])); - hif_set_edca_queue_params(wvif, &wvif->edca_params[i]); - } - wvif->uapsd_mask = 0; - hif_set_uapsd_info(wvif, wvif->uapsd_mask); wfx_tx_policy_init(wvif); wvif = NULL; From 871341db220ab0b63153daf295946137f73e727a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:27 +0000 Subject: [PATCH 143/353] staging: wfx: simplify hif_set_edca_queue_params() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct hif_req_edca_queue_params comes from hardware API. It is not intended to be manipulated in upper layers of the driver. So, this patch: 1. relocate the handling of this struct in hif_set_edca_queue_params() (the low level function) 2. replace it in wfx_vif by the mac80211 equivalent: struct ieee80211_tx_queue_params Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-44-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx.c | 20 +++++++++++++------- drivers/staging/wfx/hif_tx.h | 5 +++-- drivers/staging/wfx/queue.c | 6 +++--- drivers/staging/wfx/sta.c | 18 ++---------------- drivers/staging/wfx/wfx.h | 4 +++- 5 files changed, 24 insertions(+), 29 deletions(-) diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index 9cbf9d916f5f..259b49b99098 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -340,19 +340,25 @@ int hif_remove_key(struct wfx_dev *wdev, int idx) return ret; } -int hif_set_edca_queue_params(struct wfx_vif *wvif, - const struct hif_req_edca_queue_params *arg) +int hif_set_edca_queue_params(struct wfx_vif *wvif, u16 queue, + const struct ieee80211_tx_queue_params *arg) { int ret; struct hif_msg *hif; struct hif_req_edca_queue_params *body = wfx_alloc_hif(sizeof(*body), &hif); - // NOTE: queues numerotation are not the same between WFx and Linux - memcpy(body, arg, sizeof(*body)); - cpu_to_le16s(&body->cw_min); - cpu_to_le16s(&body->cw_max); - cpu_to_le16s(&body->tx_op_limit); + WARN_ON(arg->aifs > 255); + body->aifsn = arg->aifs; + body->cw_min = cpu_to_le16(arg->cw_min); + body->cw_max = cpu_to_le16(arg->cw_max); + body->tx_op_limit = cpu_to_le16(arg->txop * USEC_PER_TXOP); + body->queue_id = 3 - queue; + // API 2.0 has changed queue IDs values + if (wfx_api_older_than(wvif->wdev, 2, 0) && queue == IEEE80211_AC_BE) + body->queue_id = HIF_QUEUE_ID_BACKGROUND; + if (wfx_api_older_than(wvif->wdev, 2, 0) && queue == IEEE80211_AC_BK) + body->queue_id = HIF_QUEUE_ID_BESTEFFORT; wfx_fill_header(hif, wvif->id, HIF_REQ_ID_EDCA_QUEUE_PARAMS, sizeof(*body)); ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); diff --git a/drivers/staging/wfx/hif_tx.h b/drivers/staging/wfx/hif_tx.h index bb5860ee6542..d88019421fbc 100644 --- a/drivers/staging/wfx/hif_tx.h +++ b/drivers/staging/wfx/hif_tx.h @@ -12,6 +12,7 @@ #include "hif_api_cmd.h" +struct ieee80211_tx_queue_params; struct wfx_dev; struct wfx_vif; @@ -52,8 +53,8 @@ int hif_set_bss_params(struct wfx_vif *wvif, const struct hif_req_set_bss_params *arg); int hif_add_key(struct wfx_dev *wdev, const struct hif_req_add_key *arg); int hif_remove_key(struct wfx_dev *wdev, int idx); -int hif_set_edca_queue_params(struct wfx_vif *wvif, - const struct hif_req_edca_queue_params *arg); +int hif_set_edca_queue_params(struct wfx_vif *wvif, u16 queue, + const struct ieee80211_tx_queue_params *arg); int hif_start(struct wfx_vif *wvif, const struct hif_req_start *arg); int hif_beacon_transmit(struct wfx_vif *wvif, bool enable); int hif_map_link(struct wfx_vif *wvif, u8 *mac_addr, int flags, int sta_id); diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index 16216afe6cfc..abfbad7c9f75 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -443,7 +443,7 @@ static int wfx_get_prio_queue(struct wfx_vif *wvif, { static const int urgent = BIT(WFX_LINK_ID_AFTER_DTIM) | BIT(WFX_LINK_ID_UAPSD); - struct hif_req_edca_queue_params *edca; + const struct ieee80211_tx_queue_params *edca; unsigned int score, best = -1; int winner = -1; int i; @@ -458,7 +458,7 @@ static int wfx_get_prio_queue(struct wfx_vif *wvif, if (!queued) continue; *total += queued; - score = ((edca->aifsn + edca->cw_min) << 16) + + score = ((edca->aifs + edca->cw_min) << 16) + ((edca->cw_max - edca->cw_min) * (get_random_int() & 0xFFFF)); if (score < best && (winner < 0 || i != 3)) { @@ -595,7 +595,7 @@ struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev) wvif->pspoll_mask &= ~BIT(tx_priv->raw_link_id); /* allow bursting if txop is set */ - if (wvif->edca_params[queue_num].tx_op_limit) + if (wvif->edca_params[queue_num].txop) burst = (int)wfx_tx_queue_get_num_queued(queue, tx_allowed_mask) + 1; else burst = 1; diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 3504b6b3515e..19ca13543a25 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -17,7 +17,6 @@ #include "hif_tx.h" #include "hif_tx_mib.h" -#define TXOP_UNIT 32 #define HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES 2 static u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates) @@ -322,26 +321,13 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; - struct hif_req_edca_queue_params *edca; WARN_ON(queue >= hw->queues); mutex_lock(&wdev->conf_mutex); assign_bit(queue, &wvif->uapsd_mask, params->uapsd); - edca = &wvif->edca_params[queue]; - edca->aifsn = params->aifs; - edca->cw_min = params->cw_min; - edca->cw_max = params->cw_max; - edca->tx_op_limit = params->txop * TXOP_UNIT; - edca->allowed_medium_time = 0; - edca->queue_id = 3 - queue; - // API 2.0 has changed queue IDs values - if (wfx_api_older_than(wdev, 2, 0) && queue == IEEE80211_AC_BE) - edca->queue_id = HIF_QUEUE_ID_BACKGROUND; - if (wfx_api_older_than(wdev, 2, 0) && queue == IEEE80211_AC_BK) - edca->queue_id = HIF_QUEUE_ID_BESTEFFORT; - hif_set_edca_queue_params(wvif, edca); - + memcpy(&wvif->edca_params[queue], params, sizeof(*params)); + hif_set_edca_queue_params(wvif, queue, params); if (wvif->vif->type == NL80211_IFTYPE_STATION) { hif_set_uapsd_info(wvif, wvif->uapsd_mask); if (wvif->setbssparams_done && wvif->state == WFX_STATE_STA) diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 5a2f8af17eb7..f396a502283e 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -26,6 +26,8 @@ #include "hif_tx.h" #include "hif_api_general.h" +#define USEC_PER_TXOP 32 // see struct ieee80211_tx_queue_params + struct hwbus_ops; struct wfx_dev { @@ -114,7 +116,7 @@ struct wfx_vif { bool setbssparams_done; struct wfx_ht_info ht_info; unsigned long uapsd_mask; - struct hif_req_edca_queue_params edca_params[IEEE80211_NUM_ACS]; + struct ieee80211_tx_queue_params edca_params[IEEE80211_NUM_ACS]; struct hif_req_set_bss_params bss_params; struct work_struct bss_params_work; struct work_struct set_cts_work; From 154cca646720017837c811052ac2e106fbbdc8a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:28 +0000 Subject: [PATCH 144/353] staging: wfx: hif_scan() never fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If scan fails, status is returned in hif_ind_scan_cmpl. hif_scan always return a success. So, we can simplify the code. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-45-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/scan.c | 20 ++------------------ drivers/staging/wfx/scan.h | 1 - 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index 4b95e6a97df7..cdccb67cb30e 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -36,7 +36,6 @@ static void wfx_scan_restart_delayed(struct wfx_vif *wvif) static int wfx_scan_start(struct wfx_vif *wvif, struct wfx_scan_params *scan) { - int ret; int tmo = 500; if (wvif->state == WFX_STATE_PRE_STA) @@ -48,15 +47,8 @@ static int wfx_scan_start(struct wfx_vif *wvif, struct wfx_scan_params *scan) atomic_set(&wvif->wdev->scan_in_progress, 1); schedule_delayed_work(&wvif->scan.timeout, msecs_to_jiffies(tmo)); - ret = hif_scan(wvif, scan); - if (ret) { - wfx_scan_failed_cb(wvif); - atomic_set(&wvif->scan.in_progress, 0); - atomic_set(&wvif->wdev->scan_in_progress, 0); - cancel_delayed_work_sync(&wvif->scan.timeout); - wfx_scan_restart_delayed(wvif); - } - return ret; + hif_scan(wvif, scan); + return 0; } int wfx_hw_scan(struct ieee80211_hw *hw, @@ -245,14 +237,6 @@ static void wfx_scan_complete(struct wfx_vif *wvif) wfx_scan_work(&wvif->scan.work); } -void wfx_scan_failed_cb(struct wfx_vif *wvif) -{ - if (cancel_delayed_work_sync(&wvif->scan.timeout) > 0) { - wvif->scan.status = -EIO; - schedule_work(&wvif->scan.timeout.work); - } -} - void wfx_scan_complete_cb(struct wfx_vif *wvif, const struct hif_ind_scan_cmpl *arg) { diff --git a/drivers/staging/wfx/scan.h b/drivers/staging/wfx/scan.h index c7c0ab178c87..e71e5f0f522e 100644 --- a/drivers/staging/wfx/scan.h +++ b/drivers/staging/wfx/scan.h @@ -38,6 +38,5 @@ void wfx_scan_work(struct work_struct *work); void wfx_scan_timeout(struct work_struct *work); void wfx_scan_complete_cb(struct wfx_vif *wvif, const struct hif_ind_scan_cmpl *arg); -void wfx_scan_failed_cb(struct wfx_vif *wvif); #endif /* WFX_SCAN_H */ From 7ceb4753ef58185b5a90ccbd3a55373b01a38219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:29 +0000 Subject: [PATCH 145/353] staging: wfx: device already handle sleep mode during scan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The device is not allowed to enter in sleep mode during scan. However, this is already handled by the device. So driver does not have to care about it. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-46-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/bh.c | 3 +-- drivers/staging/wfx/scan.c | 3 --- drivers/staging/wfx/wfx.h | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/wfx/bh.c b/drivers/staging/wfx/bh.c index 2432ba95c2f5..983c41d1fe7c 100644 --- a/drivers/staging/wfx/bh.c +++ b/drivers/staging/wfx/bh.c @@ -271,8 +271,7 @@ static void bh_work(struct work_struct *work) if (last_op_is_rx) ack_sdio_data(wdev); - if (!wdev->hif.tx_buffers_used && !work_pending(work) && - !atomic_read(&wdev->scan_in_progress)) { + if (!wdev->hif.tx_buffers_used && !work_pending(work)) { device_release(wdev); release_chip = true; } diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index cdccb67cb30e..397fe511d34a 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -44,7 +44,6 @@ static int wfx_scan_start(struct wfx_vif *wvif, struct wfx_scan_params *scan) tmo += scan->scan_req.num_of_channels * ((20 * (scan->scan_req.max_channel_time)) + 10); atomic_set(&wvif->scan.in_progress, 1); - atomic_set(&wvif->wdev->scan_in_progress, 1); schedule_delayed_work(&wvif->scan.timeout, msecs_to_jiffies(tmo)); hif_scan(wvif, scan); @@ -232,8 +231,6 @@ fail: static void wfx_scan_complete(struct wfx_vif *wvif) { up(&wvif->scan.lock); - atomic_set(&wvif->wdev->scan_in_progress, 0); - wfx_scan_work(&wvif->scan.work); } diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index f396a502283e..97373d047f58 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -60,7 +60,6 @@ struct wfx_dev { struct mutex rx_stats_lock; int output_power; - atomic_t scan_in_progress; }; struct wfx_vif { From 1a53df55346e1381406a6f4d161aa5acfa99a01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:30 +0000 Subject: [PATCH 146/353] staging: wfx: drop useless wfx_scan_complete() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since wfx_scan_complete() is now only called from wfx_scan_complete_cb(), it make sense to merge the both functions. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-47-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/scan.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index 397fe511d34a..c043f2f79541 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -228,12 +228,6 @@ fail: schedule_work(&wvif->scan.work); } -static void wfx_scan_complete(struct wfx_vif *wvif) -{ - up(&wvif->scan.lock); - wfx_scan_work(&wvif->scan.work); -} - void wfx_scan_complete_cb(struct wfx_vif *wvif, const struct hif_ind_scan_cmpl *arg) { @@ -257,6 +251,7 @@ void wfx_scan_timeout(struct work_struct *work) wvif->scan.curr = wvif->scan.end; hif_stop_scan(wvif); } - wfx_scan_complete(wvif); + up(&wvif->scan.lock); + wfx_scan_work(&wvif->scan.work); } } From 945ce30aa52beec7eb01f3bcaf564ef60c46554a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:32 +0000 Subject: [PATCH 147/353] staging: wfx: simplify hif_scan() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structures hif_req_start_scan and hif_ssid_def come from hardware API. It is not intended to be manipulated in upper layers of the driver. So, this patch relocate handling of theses structures to hif_scan() (the low level function). This change also allows to drop struct wfx_scan_params. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-48-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx.c | 72 ++++++++++++++++++++++-------------- drivers/staging/wfx/hif_tx.h | 10 ++--- drivers/staging/wfx/scan.c | 54 ++++----------------------- drivers/staging/wfx/wfx.h | 1 + 4 files changed, 57 insertions(+), 80 deletions(-) diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index 259b49b99098..8a34a52dd5b9 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -220,41 +220,59 @@ int hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, void *val, return ret; } -int hif_scan(struct wfx_vif *wvif, const struct wfx_scan_params *arg) +int hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req, + int chan_start_idx, int chan_num) { int ret, i; struct hif_msg *hif; - struct hif_ssid_def *ssids; - size_t buf_len = sizeof(struct hif_req_start_scan) + - arg->scan_req.num_of_channels * sizeof(u8) + - arg->scan_req.num_of_ssids * sizeof(struct hif_ssid_def); - struct hif_req_start_scan *body = wfx_alloc_hif(buf_len, &hif); - u8 *ptr = (u8 *) body + sizeof(*body); + size_t buf_len = + sizeof(struct hif_req_start_scan_alt) + chan_num * sizeof(u8); + struct hif_req_start_scan_alt *body = wfx_alloc_hif(buf_len, &hif); + int tmo_chan_fg, tmo_chan_bg, tmo; - WARN(arg->scan_req.num_of_channels > HIF_API_MAX_NB_CHANNELS, "invalid params"); - WARN(arg->scan_req.num_of_ssids > 2, "invalid params"); - WARN(arg->scan_req.band > 1, "invalid params"); + WARN(chan_num > HIF_API_MAX_NB_CHANNELS, "invalid params"); + WARN(req->n_ssids > HIF_API_MAX_NB_SSIDS, "invalid params"); + + compiletime_assert(IEEE80211_MAX_SSID_LEN == HIF_API_SSID_SIZE, + "API inconsistency"); + for (i = 0; i < req->n_ssids; i++) { + memcpy(body->ssid_def[i].ssid, req->ssids[i].ssid, + IEEE80211_MAX_SSID_LEN); + body->ssid_def[i].ssid_length = + cpu_to_le32(req->ssids[i].ssid_len); + } + body->num_of_ssids = HIF_API_MAX_NB_SSIDS; + // Background scan is always a good idea + body->scan_type.type = 1; + body->scan_flags.fbg = 1; + body->tx_power_level = + cpu_to_le32(req->channels[chan_start_idx]->max_power); + body->num_of_channels = chan_num; + for (i = 0; i < chan_num; i++) + body->channel_list[i] = + req->channels[i + chan_start_idx]->hw_value; + if (req->no_cck) + body->max_transmit_rate = API_RATE_INDEX_G_6MBPS; + else + body->max_transmit_rate = API_RATE_INDEX_B_1MBPS; + if (req->channels[chan_start_idx]->flags & IEEE80211_CHAN_NO_IR) { + body->min_channel_time = cpu_to_le32(50); + body->max_channel_time = cpu_to_le32(150); + } else { + body->min_channel_time = cpu_to_le32(10); + body->max_channel_time = cpu_to_le32(50); + body->num_of_probe_requests = 2; + body->probe_delay = 100; + } + tmo_chan_bg = le32_to_cpu(body->max_channel_time) * USEC_PER_TU; + tmo_chan_fg = 512 * USEC_PER_TU + body->probe_delay; + tmo_chan_fg *= body->num_of_probe_requests; + tmo = chan_num * max(tmo_chan_bg, tmo_chan_fg); - // FIXME: This API is unnecessary complex, fixing NumOfChannels and - // adding a member SsidDef at end of struct hif_req_start_scan would - // simplify that a lot. - memcpy(body, &arg->scan_req, sizeof(*body)); - cpu_to_le32s(&body->min_channel_time); - cpu_to_le32s(&body->max_channel_time); - cpu_to_le32s(&body->tx_power_level); - memcpy(ptr, arg->ssids, - arg->scan_req.num_of_ssids * sizeof(struct hif_ssid_def)); - ssids = (struct hif_ssid_def *) ptr; - for (i = 0; i < body->num_of_ssids; ++i) - cpu_to_le32s(&ssids[i].ssid_length); - ptr += arg->scan_req.num_of_ssids * sizeof(struct hif_ssid_def); - memcpy(ptr, arg->ch, arg->scan_req.num_of_channels * sizeof(u8)); - ptr += arg->scan_req.num_of_channels * sizeof(u8); - WARN(buf_len != ptr - (u8 *) body, "allocation size mismatch"); wfx_fill_header(hif, wvif->id, HIF_REQ_ID_START_SCAN, buf_len); ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); kfree(hif); - return ret; + return ret ? ret : usecs_to_jiffies(tmo); } int hif_stop_scan(struct wfx_vif *wvif) diff --git a/drivers/staging/wfx/hif_tx.h b/drivers/staging/wfx/hif_tx.h index d88019421fbc..e8855ead3a18 100644 --- a/drivers/staging/wfx/hif_tx.h +++ b/drivers/staging/wfx/hif_tx.h @@ -13,15 +13,10 @@ #include "hif_api_cmd.h" struct ieee80211_tx_queue_params; +struct cfg80211_scan_request; struct wfx_dev; struct wfx_vif; -struct wfx_scan_params { - struct hif_req_start_scan scan_req; - struct hif_ssid_def *ssids; - u8 *ch; -}; - struct wfx_hif_cmd { struct mutex lock; struct mutex key_renew_lock; @@ -45,7 +40,8 @@ int hif_read_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, void *buf, size_t buf_size); int hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, void *buf, size_t buf_size); -int hif_scan(struct wfx_vif *wvif, const struct wfx_scan_params *arg); +int hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req80211, + int chan_start, int chan_num); int hif_stop_scan(struct wfx_vif *wvif); int hif_join(struct wfx_vif *wvif, const struct hif_req_join *arg); int hif_set_pm(struct wfx_vif *wvif, bool ps, int dynamic_ps_timeout); diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index c043f2f79541..122da87bbf92 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -34,19 +34,18 @@ static void wfx_scan_restart_delayed(struct wfx_vif *wvif) } } -static int wfx_scan_start(struct wfx_vif *wvif, struct wfx_scan_params *scan) +static int wfx_scan_start(struct wfx_vif *wvif, + int chan_start_idx, int chan_num) { - int tmo = 500; + int tmo; if (wvif->state == WFX_STATE_PRE_STA) return -EBUSY; - tmo += scan->scan_req.num_of_channels * - ((20 * (scan->scan_req.max_channel_time)) + 10); atomic_set(&wvif->scan.in_progress, 1); - schedule_delayed_work(&wvif->scan.timeout, msecs_to_jiffies(tmo)); - hif_scan(wvif, scan); + tmo = hif_scan(wvif, wvif->scan.req, chan_start_idx, chan_num); + schedule_delayed_work(&wvif->scan.timeout, tmo); return 0; } @@ -128,9 +127,6 @@ void wfx_scan_work(struct work_struct *work) { struct wfx_vif *wvif = container_of(work, struct wfx_vif, scan.work); struct ieee80211_channel **it; - struct wfx_scan_params scan = { - .scan_req.scan_type.type = 0, /* Foreground */ - }; struct ieee80211_channel *first; int i; @@ -173,48 +169,14 @@ void wfx_scan_work(struct work_struct *work) (*it)->max_power != first->max_power) break; } - scan.scan_req.band = first->band; - - if (wvif->scan.req->no_cck) - scan.scan_req.max_transmit_rate = API_RATE_INDEX_G_6MBPS; - else - scan.scan_req.max_transmit_rate = API_RATE_INDEX_B_1MBPS; - scan.scan_req.num_of_probe_requests = - (first->flags & IEEE80211_CHAN_NO_IR) ? 0 : 2; - scan.scan_req.num_of_ssids = wvif->scan.n_ssids; - scan.ssids = &wvif->scan.ssids[0]; - scan.scan_req.num_of_channels = it - wvif->scan.curr; - scan.scan_req.probe_delay = 100; - // FIXME: Check if FW can do active scan while joined. - if (wvif->state == WFX_STATE_STA) { - scan.scan_req.scan_type.type = 1; - scan.scan_req.scan_flags.fbg = 1; - } - - scan.ch = kcalloc(scan.scan_req.num_of_channels, - sizeof(u8), GFP_KERNEL); - - if (!scan.ch) { - wvif->scan.status = -ENOMEM; - goto fail; - } - for (i = 0; i < scan.scan_req.num_of_channels; ++i) - scan.ch[i] = wvif->scan.curr[i]->hw_value; - - if (wvif->scan.curr[0]->flags & IEEE80211_CHAN_NO_IR) { - scan.scan_req.min_channel_time = 50; - scan.scan_req.max_channel_time = 150; - } else { - scan.scan_req.min_channel_time = 10; - scan.scan_req.max_channel_time = 50; - } if (!(first->flags & IEEE80211_CHAN_NO_IR) && wvif->scan.output_power != first->max_power) { wvif->scan.output_power = first->max_power; hif_set_output_power(wvif, wvif->scan.output_power * 10); } - wvif->scan.status = wfx_scan_start(wvif, &scan); - kfree(scan.ch); + wvif->scan.status = wfx_scan_start(wvif, + wvif->scan.curr - wvif->scan.begin, + it - wvif->scan.curr); if (wvif->scan.status) goto fail; wvif->scan.curr = it; diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 97373d047f58..35f5ddc2eeb3 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -27,6 +27,7 @@ #include "hif_api_general.h" #define USEC_PER_TXOP 32 // see struct ieee80211_tx_queue_params +#define USEC_PER_TU 1024 struct hwbus_ops; From 397f36c1c786b70fa24a27fde7c425fcf34313fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:33 +0000 Subject: [PATCH 148/353] staging: wfx: introduce update_probe_tmpl() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify wfx_hw_scan() by splitting out the update of the probe request. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-49-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/scan.c | 59 ++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index 122da87bbf92..8b184efad0cf 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -49,6 +49,27 @@ static int wfx_scan_start(struct wfx_vif *wvif, return 0; } +static int update_probe_tmpl(struct wfx_vif *wvif, + struct cfg80211_scan_request *req) +{ + struct hif_mib_template_frame *tmpl; + struct sk_buff *skb; + + skb = ieee80211_probereq_get(wvif->wdev->hw, wvif->vif->addr, + NULL, 0, req->ie_len); + if (!skb) + return -ENOMEM; + + skb_put_data(skb, req->ie, req->ie_len); + skb_push(skb, 4); + tmpl = (struct hif_mib_template_frame *)skb->data; + tmpl->frame_type = HIF_TMPLT_PRBREQ; + tmpl->frame_length = cpu_to_le16(skb->len - 4); + hif_set_template_frame(wvif, tmpl); + dev_kfree_skb(skb); + return 0; +} + int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *hw_req) @@ -56,9 +77,7 @@ int wfx_hw_scan(struct ieee80211_hw *hw, struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; struct cfg80211_scan_request *req = &hw_req->req; - struct sk_buff *skb; int i, ret; - struct hif_mib_template_frame *p; if (!wvif) return -EINVAL; @@ -72,29 +91,15 @@ int wfx_hw_scan(struct ieee80211_hw *hw, if (req->n_ssids > HIF_API_MAX_NB_SSIDS) return -EINVAL; - skb = ieee80211_probereq_get(hw, wvif->vif->addr, NULL, 0, req->ie_len); - if (!skb) - return -ENOMEM; - - if (req->ie_len) - memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len); - mutex_lock(&wdev->conf_mutex); - p = (struct hif_mib_template_frame *)skb_push(skb, 4); - p->frame_type = HIF_TMPLT_PRBREQ; - p->frame_length = cpu_to_le16(skb->len - 4); - ret = hif_set_template_frame(wvif, p); - skb_pull(skb, 4); + ret = update_probe_tmpl(wvif, req); + if (ret) + goto failed; - if (!ret) - /* Host want to be the probe responder. */ - ret = wfx_fwd_probe_req(wvif, true); - if (ret) { - mutex_unlock(&wdev->conf_mutex); - dev_kfree_skb(skb); - return ret; - } + ret = wfx_fwd_probe_req(wvif, true); + if (ret) + goto failed; wfx_tx_lock_flush(wdev); @@ -114,13 +119,11 @@ int wfx_hw_scan(struct ieee80211_hw *hw, dst->ssid_length = req->ssids[i].ssid_len; ++wvif->scan.n_ssids; } - - mutex_unlock(&wdev->conf_mutex); - - if (skb) - dev_kfree_skb(skb); schedule_work(&wvif->scan.work); - return 0; + +failed: + mutex_unlock(&wdev->conf_mutex); + return ret; } void wfx_scan_work(struct work_struct *work) From 094ecec9be6096960cb4ae6a6256759bbba7aa0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:34 +0000 Subject: [PATCH 149/353] staging: wfx: simplify hif_set_template_frame() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structure hif_mib_template_frame come from hardware API. It is not intended to be manipulated in upper layers of the driver. In add, the current code for hif_set_template_frame() is dumb. All the difficult task is left to the caller. So, there is code to factorize here. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-50-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx_mib.h | 11 ++++++++++- drivers/staging/wfx/scan.c | 7 +------ drivers/staging/wfx/sta.c | 29 +++++++---------------------- 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index d77765f75f10..b1eeda2a3ab3 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -130,8 +130,17 @@ static inline int hif_set_operational_mode(struct wfx_dev *wdev, } static inline int hif_set_template_frame(struct wfx_vif *wvif, - struct hif_mib_template_frame *arg) + struct sk_buff *skb, + u8 frame_type, int init_rate) { + struct hif_mib_template_frame *arg; + + skb_push(skb, 4); + arg = (struct hif_mib_template_frame *)skb->data; + skb_pull(skb, 4); + arg->init_rate = init_rate; + arg->frame_type = frame_type; + arg->frame_length = cpu_to_le16(skb->len); return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_TEMPLATE_FRAME, arg, sizeof(*arg)); } diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index 8b184efad0cf..c82c04ff5d06 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -52,7 +52,6 @@ static int wfx_scan_start(struct wfx_vif *wvif, static int update_probe_tmpl(struct wfx_vif *wvif, struct cfg80211_scan_request *req) { - struct hif_mib_template_frame *tmpl; struct sk_buff *skb; skb = ieee80211_probereq_get(wvif->wdev->hw, wvif->vif->addr, @@ -61,11 +60,7 @@ static int update_probe_tmpl(struct wfx_vif *wvif, return -ENOMEM; skb_put_data(skb, req->ie, req->ie_len); - skb_push(skb, 4); - tmpl = (struct hif_mib_template_frame *)skb->data; - tmpl->frame_type = HIF_TMPLT_PRBREQ; - tmpl->frame_length = cpu_to_le16(skb->len - 4); - hif_set_template_frame(wvif, tmpl); + hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBREQ, 0); dev_kfree_skb(skb); return 0; } diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 19ca13543a25..ba3e81fd477b 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -831,32 +831,20 @@ static int wfx_update_beaconing(struct wfx_vif *wvif) static int wfx_upload_beacon(struct wfx_vif *wvif) { - int ret = 0; - struct sk_buff *skb = NULL; + struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - struct hif_mib_template_frame *p; if (wvif->vif->type == NL80211_IFTYPE_STATION || wvif->vif->type == NL80211_IFTYPE_MONITOR || wvif->vif->type == NL80211_IFTYPE_UNSPECIFIED) - goto done; + return 0; skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif); - if (!skb) return -ENOMEM; + hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN, + API_RATE_INDEX_B_1MBPS); - p = (struct hif_mib_template_frame *) skb_push(skb, 4); - p->frame_type = HIF_TMPLT_BCN; - p->init_rate = API_RATE_INDEX_B_1MBPS; /* 1Mbps DSSS */ - p->frame_length = cpu_to_le16(skb->len - 4); - - ret = hif_set_template_frame(wvif, p); - - skb_pull(skb, 4); - - if (ret) - goto done; /* TODO: Distill probe resp; remove TIM and any other beacon-specific * IEs */ @@ -864,14 +852,11 @@ static int wfx_upload_beacon(struct wfx_vif *wvif) mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); - p->frame_type = HIF_TMPLT_PRBRES; - - ret = hif_set_template_frame(wvif, p); + hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES, + API_RATE_INDEX_B_1MBPS); wfx_fwd_probe_req(wvif, false); - -done: dev_kfree_skb(skb); - return ret; + return 0; } static int wfx_is_ht(const struct wfx_ht_info *ht_info) From d1c015b4ef6f2ab74b19c216cfff07742b7665cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:35 +0000 Subject: [PATCH 150/353] staging: wfx: rewrite wfx_hw_scan() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Scan requests from mac80211 must be splitted in a few hardware requests (it is necessary to split channels with active scan and channels with passive scan). Current code schedules a work_struct for each hardware request and one delayed_work to handle scan timeout. It is far simpler to run send all the hardware requests synchronously and replace delayed_work with a simple wait_for_completion_timeout(). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-51-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_rx.c | 2 +- drivers/staging/wfx/scan.c | 227 ++++++++++------------------------- drivers/staging/wfx/scan.h | 23 +--- drivers/staging/wfx/sta.c | 39 ++---- drivers/staging/wfx/wfx.h | 4 +- 5 files changed, 82 insertions(+), 213 deletions(-) diff --git a/drivers/staging/wfx/hif_rx.c b/drivers/staging/wfx/hif_rx.c index 8a3ccdc60b7d..408967a4c457 100644 --- a/drivers/staging/wfx/hif_rx.c +++ b/drivers/staging/wfx/hif_rx.c @@ -206,7 +206,7 @@ static int hif_scan_complete_indication(struct wfx_dev *wdev, const struct hif_ind_scan_cmpl *body = buf; WARN_ON(!wvif); - wfx_scan_complete_cb(wvif, body); + wfx_scan_complete(wvif, body); return 0; } diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index c82c04ff5d06..b73e61e8da46 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -22,33 +22,6 @@ static void __ieee80211_scan_completed_compat(struct ieee80211_hw *hw, ieee80211_scan_completed(hw, &info); } -static void wfx_scan_restart_delayed(struct wfx_vif *wvif) -{ - if (wvif->delayed_unjoin) { - wvif->delayed_unjoin = false; - if (!schedule_work(&wvif->unjoin_work)) - wfx_tx_unlock(wvif->wdev); - } else if (wvif->delayed_link_loss) { - wvif->delayed_link_loss = 0; - wfx_cqm_bssloss_sm(wvif, 1, 0, 0); - } -} - -static int wfx_scan_start(struct wfx_vif *wvif, - int chan_start_idx, int chan_num) -{ - int tmo; - - if (wvif->state == WFX_STATE_PRE_STA) - return -EBUSY; - - atomic_set(&wvif->scan.in_progress, 1); - - tmo = hif_scan(wvif, wvif->scan.req, chan_start_idx, chan_num); - schedule_delayed_work(&wvif->scan.timeout, tmo); - return 0; -} - static int update_probe_tmpl(struct wfx_vif *wvif, struct cfg80211_scan_request *req) { @@ -65,153 +38,81 @@ static int update_probe_tmpl(struct wfx_vif *wvif, return 0; } -int wfx_hw_scan(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_scan_request *hw_req) +static int send_scan_req(struct wfx_vif *wvif, + struct cfg80211_scan_request *req, int start_idx) +{ + int i, ret, timeout; + struct ieee80211_channel *ch_start, *ch_cur; + + for (i = start_idx; i < req->n_channels; i++) { + ch_start = req->channels[start_idx]; + ch_cur = req->channels[i]; + WARN(ch_cur->band != NL80211_BAND_2GHZ, "band not supported"); + if (ch_cur->max_power != ch_start->max_power) + break; + if ((ch_cur->flags ^ ch_start->flags) & IEEE80211_CHAN_NO_IR) + break; + } + wfx_tx_lock_flush(wvif->wdev); + reinit_completion(&wvif->scan_complete); + ret = hif_scan(wvif, req, start_idx, i - start_idx); + if (ret < 0) + return ret; + timeout = ret; + ret = wait_for_completion_timeout(&wvif->scan_complete, timeout); + if (req->channels[start_idx]->max_power != wvif->wdev->output_power) + hif_set_output_power(wvif, wvif->wdev->output_power * 10); + wfx_tx_unlock(wvif->wdev); + if (!ret) { + dev_notice(wvif->wdev->dev, "scan timeout\n"); + hif_stop_scan(wvif); + return -ETIMEDOUT; + } + return i - start_idx; +} + +int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_scan_request *hw_req) { struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; - struct cfg80211_scan_request *req = &hw_req->req; - int i, ret; + int chan_cur, ret; - if (!wvif) - return -EINVAL; + WARN_ON(hw_req->req.n_channels > HIF_API_MAX_NB_CHANNELS); - if (wvif->state == WFX_STATE_AP) + if (vif->type == NL80211_IFTYPE_AP) return -EOPNOTSUPP; - if (req->n_ssids == 1 && !req->ssids[0].ssid_len) - req->n_ssids = 0; - - if (req->n_ssids > HIF_API_MAX_NB_SSIDS) - return -EINVAL; + if (wvif->state == WFX_STATE_PRE_STA) + return -EBUSY; + mutex_lock(&wvif->scan_lock); mutex_lock(&wdev->conf_mutex); - - ret = update_probe_tmpl(wvif, req); - if (ret) - goto failed; - - ret = wfx_fwd_probe_req(wvif, true); - if (ret) - goto failed; - - wfx_tx_lock_flush(wdev); - - WARN(wvif->scan.req, "unexpected concurrent scan"); - wvif->scan.req = req; - wvif->scan.n_ssids = 0; - wvif->scan.status = 0; - wvif->scan.begin = &req->channels[0]; - wvif->scan.curr = wvif->scan.begin; - wvif->scan.end = &req->channels[req->n_channels]; - wvif->scan.output_power = wdev->output_power; - - for (i = 0; i < req->n_ssids; ++i) { - struct hif_ssid_def *dst = &wvif->scan.ssids[wvif->scan.n_ssids]; - - memcpy(&dst->ssid[0], req->ssids[i].ssid, sizeof(dst->ssid)); - dst->ssid_length = req->ssids[i].ssid_len; - ++wvif->scan.n_ssids; - } - schedule_work(&wvif->scan.work); - -failed: + update_probe_tmpl(wvif, &hw_req->req); + wfx_fwd_probe_req(wvif, true); + chan_cur = 0; + do { + ret = send_scan_req(wvif, &hw_req->req, chan_cur); + if (ret > 0) + chan_cur += ret; + } while (ret > 0 && chan_cur < hw_req->req.n_channels); + __ieee80211_scan_completed_compat(hw, ret < 0); mutex_unlock(&wdev->conf_mutex); - return ret; + mutex_unlock(&wvif->scan_lock); + if (wvif->delayed_unjoin) { + wvif->delayed_unjoin = false; + wfx_tx_lock(wdev); + if (!schedule_work(&wvif->unjoin_work)) + wfx_tx_unlock(wdev); + } else if (wvif->delayed_link_loss) { + wvif->delayed_link_loss = false; + wfx_cqm_bssloss_sm(wvif, 1, 0, 0); + } + return 0; } -void wfx_scan_work(struct work_struct *work) +void wfx_scan_complete(struct wfx_vif *wvif, + const struct hif_ind_scan_cmpl *arg) { - struct wfx_vif *wvif = container_of(work, struct wfx_vif, scan.work); - struct ieee80211_channel **it; - struct ieee80211_channel *first; - int i; - - down(&wvif->scan.lock); - mutex_lock(&wvif->wdev->conf_mutex); - - - if (!wvif->scan.req || wvif->scan.curr == wvif->scan.end) { - if (wvif->scan.output_power != wvif->wdev->output_power) - hif_set_output_power(wvif, - wvif->wdev->output_power * 10); - - if (wvif->scan.status < 0) - dev_warn(wvif->wdev->dev, "scan failed\n"); - else if (wvif->scan.req) - dev_dbg(wvif->wdev->dev, "scan completed\n"); - else - dev_dbg(wvif->wdev->dev, "scan canceled\n"); - - wvif->scan.req = NULL; - wfx_scan_restart_delayed(wvif); - wfx_tx_unlock(wvif->wdev); - mutex_unlock(&wvif->wdev->conf_mutex); - __ieee80211_scan_completed_compat(wvif->wdev->hw, - wvif->scan.status ? 1 : 0); - up(&wvif->scan.lock); - return; - } - first = *wvif->scan.curr; - - for (it = wvif->scan.curr + 1, i = 1; - it != wvif->scan.end && i < HIF_API_MAX_NB_CHANNELS; - ++it, ++i) { - if ((*it)->band != first->band) - break; - if (((*it)->flags ^ first->flags) & - IEEE80211_CHAN_NO_IR) - break; - if (!(first->flags & IEEE80211_CHAN_NO_IR) && - (*it)->max_power != first->max_power) - break; - } - if (!(first->flags & IEEE80211_CHAN_NO_IR) && - wvif->scan.output_power != first->max_power) { - wvif->scan.output_power = first->max_power; - hif_set_output_power(wvif, wvif->scan.output_power * 10); - } - wvif->scan.status = wfx_scan_start(wvif, - wvif->scan.curr - wvif->scan.begin, - it - wvif->scan.curr); - if (wvif->scan.status) - goto fail; - wvif->scan.curr = it; - mutex_unlock(&wvif->wdev->conf_mutex); - return; - -fail: - wvif->scan.curr = wvif->scan.end; - mutex_unlock(&wvif->wdev->conf_mutex); - up(&wvif->scan.lock); - schedule_work(&wvif->scan.work); -} - -void wfx_scan_complete_cb(struct wfx_vif *wvif, - const struct hif_ind_scan_cmpl *arg) -{ - if (cancel_delayed_work_sync(&wvif->scan.timeout) > 0) { - wvif->scan.status = 1; - schedule_work(&wvif->scan.timeout.work); - } -} - -void wfx_scan_timeout(struct work_struct *work) -{ - struct wfx_vif *wvif = container_of(work, struct wfx_vif, - scan.timeout.work); - - if (atomic_xchg(&wvif->scan.in_progress, 0)) { - if (wvif->scan.status > 0) { - wvif->scan.status = 0; - } else if (!wvif->scan.status) { - dev_warn(wvif->wdev->dev, "timeout waiting for scan complete notification\n"); - wvif->scan.status = -ETIMEDOUT; - wvif->scan.curr = wvif->scan.end; - hif_stop_scan(wvif); - } - up(&wvif->scan.lock); - wfx_scan_work(&wvif->scan.work); - } + complete(&wvif->scan_complete); } diff --git a/drivers/staging/wfx/scan.h b/drivers/staging/wfx/scan.h index e71e5f0f522e..03bc6c7e562d 100644 --- a/drivers/staging/wfx/scan.h +++ b/drivers/staging/wfx/scan.h @@ -8,8 +8,6 @@ #ifndef WFX_SCAN_H #define WFX_SCAN_H -#include -#include #include #include "hif_api_cmd.h" @@ -17,26 +15,9 @@ struct wfx_dev; struct wfx_vif; -struct wfx_scan { - struct semaphore lock; - struct work_struct work; - struct delayed_work timeout; - struct cfg80211_scan_request *req; - struct ieee80211_channel **begin; - struct ieee80211_channel **curr; - struct ieee80211_channel **end; - struct hif_ssid_def ssids[HIF_API_MAX_NB_SSIDS]; - int output_power; - int n_ssids; - int status; - atomic_t in_progress; -}; - int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *req); -void wfx_scan_work(struct work_struct *work); -void wfx_scan_timeout(struct work_struct *work); -void wfx_scan_complete_cb(struct wfx_vif *wvif, - const struct hif_ind_scan_cmpl *arg); +void wfx_scan_complete(struct wfx_vif *wvif, + const struct hif_ind_scan_cmpl *ind); #endif /* WFX_SCAN_H */ diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index ba3e81fd477b..16f5db873275 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -277,13 +277,13 @@ void wfx_configure_filter(struct ieee80211_hw *hw, *total_flags &= FIF_OTHER_BSS | FIF_FCSFAIL | FIF_PROBE_REQ; while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { - down(&wvif->scan.lock); + mutex_lock(&wvif->scan_lock); wvif->filter_bssid = (*total_flags & (FIF_OTHER_BSS | FIF_PROBE_REQ)) ? 0 : 1; wvif->disable_beacon_filter = !(*total_flags & FIF_PROBE_REQ); wfx_fwd_probe_req(wvif, true); wfx_update_filtering(wvif); - up(&wvif->scan.lock); + mutex_unlock(&wvif->scan_lock); } } @@ -433,9 +433,9 @@ static void wfx_event_handler_work(struct work_struct *work) switch (event->evt.event_id) { case HIF_EVENT_IND_BSSLOST: cancel_work_sync(&wvif->unjoin_work); - if (!down_trylock(&wvif->scan.lock)) { + if (mutex_trylock(&wvif->scan_lock)) { wfx_cqm_bssloss_sm(wvif, 1, 0, 0); - up(&wvif->scan.lock); + mutex_unlock(&wvif->scan_lock); } else { /* Scan is in progress. Delay reporting. * Scan complete will trigger bss_loss_work @@ -501,7 +501,7 @@ static void wfx_do_unjoin(struct wfx_vif *wvif) { mutex_lock(&wvif->wdev->conf_mutex); - if (atomic_read(&wvif->scan.in_progress)) { + if (!mutex_trylock(&wvif->scan_lock)) { if (wvif->delayed_unjoin) dev_dbg(wvif->wdev->dev, "delayed unjoin is already scheduled\n"); @@ -509,6 +509,7 @@ static void wfx_do_unjoin(struct wfx_vif *wvif) wvif->delayed_unjoin = true; goto done; } + mutex_unlock(&wvif->scan_lock); wvif->delayed_link_loss = false; @@ -613,14 +614,6 @@ static void wfx_do_join(struct wfx_vif *wvif) mutex_lock(&wvif->wdev->conf_mutex); - /* Under the conf lock: check scan status and - * bail out if it is in progress. - */ - if (atomic_read(&wvif->scan.in_progress)) { - wfx_tx_unlock(wvif->wdev); - goto done_put; - } - /* Sanity check basic rates */ if (!join.basic_rate_set) join.basic_rate_set = 7; @@ -684,7 +677,6 @@ static void wfx_do_join(struct wfx_vif *wvif) } wfx_update_filtering(wvif); -done_put: mutex_unlock(&wvif->wdev->conf_mutex); if (bss) cfg80211_put_bss(wvif->wdev->hw->wiphy, bss); @@ -1346,7 +1338,7 @@ int wfx_config(struct ieee80211_hw *hw, u32 changed) return 0; } - down(&wvif->scan.lock); + mutex_lock(&wvif->scan_lock); mutex_lock(&wdev->conf_mutex); if (changed & IEEE80211_CONF_CHANGE_POWER) { wdev->output_power = conf->power_level; @@ -1361,7 +1353,7 @@ int wfx_config(struct ieee80211_hw *hw, u32 changed) } mutex_unlock(&wdev->conf_mutex); - up(&wvif->scan.lock); + mutex_unlock(&wvif->scan_lock); return ret; } @@ -1419,10 +1411,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) wvif->wep_default_key_id = -1; INIT_WORK(&wvif->wep_key_work, wfx_wep_key_work); - sema_init(&wvif->scan.lock, 1); - INIT_WORK(&wvif->scan.work, wfx_scan_work); - INIT_DELAYED_WORK(&wvif->scan.timeout, wfx_scan_timeout); - spin_lock_init(&wvif->event_queue_lock); INIT_LIST_HEAD(&wvif->event_queue); INIT_WORK(&wvif->event_handler_work, wfx_event_handler_work); @@ -1435,8 +1423,11 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) INIT_WORK(&wvif->bss_params_work, wfx_bss_params_work); INIT_WORK(&wvif->set_cts_work, wfx_set_cts_work); INIT_WORK(&wvif->unjoin_work, wfx_unjoin_work); - INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work); + + mutex_init(&wvif->scan_lock); + init_completion(&wvif->scan_complete); + mutex_unlock(&wdev->conf_mutex); hif_set_macaddr(wvif, vif->addr); @@ -1462,10 +1453,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw, struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; int i; - // If scan is in progress, stop it - while (down_trylock(&wvif->scan.lock)) - schedule(); - up(&wvif->scan.lock); wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300)); mutex_lock(&wdev->conf_mutex); @@ -1505,8 +1492,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw, /* FIXME: In add to reset MAC address, try to reset interface */ hif_set_macaddr(wvif, NULL); - cancel_delayed_work_sync(&wvif->scan.timeout); - wfx_cqm_bssloss_sm(wvif, 0, 0, 0); cancel_work_sync(&wvif->unjoin_work); cancel_delayed_work_sync(&wvif->link_id_gc_work); diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 35f5ddc2eeb3..3356d0cbf7af 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -125,7 +125,9 @@ struct wfx_vif { bool delayed_unjoin; struct work_struct unjoin_work; - struct wfx_scan scan; + /* avoid some operations in parallel with scan */ + struct mutex scan_lock; + struct completion scan_complete; struct completion set_pm_mode_complete; From 3827e33d371ed2f4024fd42a4409e1b7af8e0938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:37 +0000 Subject: [PATCH 151/353] staging: wfx: workaround bug with "iw scan" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mac80211 specification does not forbid hw_scan() to call ieee80211_scan_completed(). However, from userspace point of view, not all applications support this behavior. In particular, the code of iw contains a big fat warning: /* * This code has a bug, which requires creating a separate * nl80211 socket to fix: * It is possible for a NL80211_CMD_NEW_SCAN_RESULTS or * NL80211_CMD_SCAN_ABORTED message to be sent by the kernel * before (!) we listen to it, because we only start listening * after we send our scan request. [...] * Alas, the kernel doesn't do that (yet). */ So, we have to avoid to call ieee80211_scan_completed() from hw_scan() (it's a kind of unwritten rule). This patch relocates the hw_scan() process to a work_struct to fix the problem. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-52-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/scan.c | 63 +++++++++++++++++++++++--------------- drivers/staging/wfx/scan.h | 1 + drivers/staging/wfx/sta.c | 1 + drivers/staging/wfx/wfx.h | 2 ++ 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index b73e61e8da46..540009b72240 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -71,12 +71,45 @@ static int send_scan_req(struct wfx_vif *wvif, return i - start_idx; } +/* + * It is not really necessary to run scan request asynchronously. However, + * there is a bug in "iw scan" when ieee80211_scan_completed() is called before + * wfx_hw_scan() return + */ +void wfx_hw_scan_work(struct work_struct *work) +{ + struct wfx_vif *wvif = container_of(work, struct wfx_vif, scan_work); + struct ieee80211_scan_request *hw_req = wvif->scan_req; + int chan_cur, ret; + + mutex_lock(&wvif->scan_lock); + mutex_lock(&wvif->wdev->conf_mutex); + update_probe_tmpl(wvif, &hw_req->req); + wfx_fwd_probe_req(wvif, true); + chan_cur = 0; + do { + ret = send_scan_req(wvif, &hw_req->req, chan_cur); + if (ret > 0) + chan_cur += ret; + } while (ret > 0 && chan_cur < hw_req->req.n_channels); + mutex_unlock(&wvif->wdev->conf_mutex); + mutex_unlock(&wvif->scan_lock); + __ieee80211_scan_completed_compat(wvif->wdev->hw, ret < 0); + if (wvif->delayed_unjoin) { + wvif->delayed_unjoin = false; + wfx_tx_lock(wvif->wdev); + if (!schedule_work(&wvif->unjoin_work)) + wfx_tx_unlock(wvif->wdev); + } else if (wvif->delayed_link_loss) { + wvif->delayed_link_loss = false; + wfx_cqm_bssloss_sm(wvif, 1, 0, 0); + } +} + int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *hw_req) { - struct wfx_dev *wdev = hw->priv; - struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; - int chan_cur, ret; + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; WARN_ON(hw_req->req.n_channels > HIF_API_MAX_NB_CHANNELS); @@ -86,28 +119,8 @@ int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (wvif->state == WFX_STATE_PRE_STA) return -EBUSY; - mutex_lock(&wvif->scan_lock); - mutex_lock(&wdev->conf_mutex); - update_probe_tmpl(wvif, &hw_req->req); - wfx_fwd_probe_req(wvif, true); - chan_cur = 0; - do { - ret = send_scan_req(wvif, &hw_req->req, chan_cur); - if (ret > 0) - chan_cur += ret; - } while (ret > 0 && chan_cur < hw_req->req.n_channels); - __ieee80211_scan_completed_compat(hw, ret < 0); - mutex_unlock(&wdev->conf_mutex); - mutex_unlock(&wvif->scan_lock); - if (wvif->delayed_unjoin) { - wvif->delayed_unjoin = false; - wfx_tx_lock(wdev); - if (!schedule_work(&wvif->unjoin_work)) - wfx_tx_unlock(wdev); - } else if (wvif->delayed_link_loss) { - wvif->delayed_link_loss = false; - wfx_cqm_bssloss_sm(wvif, 1, 0, 0); - } + wvif->scan_req = hw_req; + schedule_work(&wvif->scan_work); return 0; } diff --git a/drivers/staging/wfx/scan.h b/drivers/staging/wfx/scan.h index 03bc6c7e562d..b547f1927d72 100644 --- a/drivers/staging/wfx/scan.h +++ b/drivers/staging/wfx/scan.h @@ -15,6 +15,7 @@ struct wfx_dev; struct wfx_vif; +void wfx_hw_scan_work(struct work_struct *work); int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *req); void wfx_scan_complete(struct wfx_vif *wvif, diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 16f5db873275..4354bb8081c5 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -1427,6 +1427,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) mutex_init(&wvif->scan_lock); init_completion(&wvif->scan_complete); + INIT_WORK(&wvif->scan_work, wfx_hw_scan_work); mutex_unlock(&wdev->conf_mutex); diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 3356d0cbf7af..b5f763c3fac7 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -127,7 +127,9 @@ struct wfx_vif { /* avoid some operations in parallel with scan */ struct mutex scan_lock; + struct work_struct scan_work; struct completion scan_complete; + struct ieee80211_scan_request *scan_req; struct completion set_pm_mode_complete; From 9699c88a4427d592655977a8cbeae46864df7700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:38 +0000 Subject: [PATCH 152/353] staging: wfx: delayed_unjoin cannot happen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original code allows to detect an unjoin request during a scan and delaying the unjoin request. However, it is far easier to just block the unjoin request until the end of the scan request. In fact, it is already the case since scan and unjoin are protected by conf_mutex. So, currently, the handling of delayed_unjoin is just dead code. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-53-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/scan.c | 7 +------ drivers/staging/wfx/sta.c | 14 -------------- drivers/staging/wfx/wfx.h | 1 - 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index 540009b72240..bdbce6926e91 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -95,12 +95,7 @@ void wfx_hw_scan_work(struct work_struct *work) mutex_unlock(&wvif->wdev->conf_mutex); mutex_unlock(&wvif->scan_lock); __ieee80211_scan_completed_compat(wvif->wdev->hw, ret < 0); - if (wvif->delayed_unjoin) { - wvif->delayed_unjoin = false; - wfx_tx_lock(wvif->wdev); - if (!schedule_work(&wvif->unjoin_work)) - wfx_tx_unlock(wvif->wdev); - } else if (wvif->delayed_link_loss) { + if (wvif->delayed_link_loss) { wvif->delayed_link_loss = false; wfx_cqm_bssloss_sm(wvif, 1, 0, 0); } diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 4354bb8081c5..7ae763e96455 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -66,10 +66,6 @@ void wfx_cqm_bssloss_sm(struct wfx_vif *wvif, int init, int good, int bad) wvif->delayed_link_loss = 0; cancel_work_sync(&wvif->bss_params_work); - /* If we have a pending unjoin */ - if (wvif->delayed_unjoin) - goto end; - if (init) { schedule_delayed_work(&wvif->bss_loss_work, HZ); wvif->bss_loss_state = 0; @@ -501,16 +497,6 @@ static void wfx_do_unjoin(struct wfx_vif *wvif) { mutex_lock(&wvif->wdev->conf_mutex); - if (!mutex_trylock(&wvif->scan_lock)) { - if (wvif->delayed_unjoin) - dev_dbg(wvif->wdev->dev, - "delayed unjoin is already scheduled\n"); - else - wvif->delayed_unjoin = true; - goto done; - } - mutex_unlock(&wvif->scan_lock); - wvif->delayed_link_loss = false; if (!wvif->state) diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index b5f763c3fac7..5e7c911db024 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -122,7 +122,6 @@ struct wfx_vif { struct work_struct set_cts_work; int join_complete_status; - bool delayed_unjoin; struct work_struct unjoin_work; /* avoid some operations in parallel with scan */ From 3dc67854dfa95f7d3f132988536ace282828378a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:39 +0000 Subject: [PATCH 153/353] staging: wfx: delayed_link_loss cannot happen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original code allows to detect an BSS loss during a scan and delaying the handling of BSS loss. However, there it is no real problem to just make these two events mutually exclusive (there is just a performance penalty). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-54-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/scan.c | 4 ---- drivers/staging/wfx/sta.c | 18 +++--------------- drivers/staging/wfx/wfx.h | 1 - 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index bdbce6926e91..dde2f8868147 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -95,10 +95,6 @@ void wfx_hw_scan_work(struct work_struct *work) mutex_unlock(&wvif->wdev->conf_mutex); mutex_unlock(&wvif->scan_lock); __ieee80211_scan_completed_compat(wvif->wdev->hw, ret < 0); - if (wvif->delayed_link_loss) { - wvif->delayed_link_loss = false; - wfx_cqm_bssloss_sm(wvif, 1, 0, 0); - } } int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 7ae763e96455..3296bc3521d5 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -63,7 +63,6 @@ void wfx_cqm_bssloss_sm(struct wfx_vif *wvif, int init, int good, int bad) int tx = 0; mutex_lock(&wvif->bss_loss_lock); - wvif->delayed_link_loss = 0; cancel_work_sync(&wvif->bss_params_work); if (init) { @@ -429,18 +428,9 @@ static void wfx_event_handler_work(struct work_struct *work) switch (event->evt.event_id) { case HIF_EVENT_IND_BSSLOST: cancel_work_sync(&wvif->unjoin_work); - if (mutex_trylock(&wvif->scan_lock)) { - wfx_cqm_bssloss_sm(wvif, 1, 0, 0); - mutex_unlock(&wvif->scan_lock); - } else { - /* Scan is in progress. Delay reporting. - * Scan complete will trigger bss_loss_work - */ - wvif->delayed_link_loss = 1; - /* Also start a watchdog. */ - schedule_delayed_work(&wvif->bss_loss_work, - 5 * HZ); - } + mutex_lock(&wvif->scan_lock); + wfx_cqm_bssloss_sm(wvif, 1, 0, 0); + mutex_unlock(&wvif->scan_lock); break; case HIF_EVENT_IND_BSSREGAINED: wfx_cqm_bssloss_sm(wvif, 0, 0, 0); @@ -497,8 +487,6 @@ static void wfx_do_unjoin(struct wfx_vif *wvif) { mutex_lock(&wvif->wdev->conf_mutex); - wvif->delayed_link_loss = false; - if (!wvif->state) goto done; diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 5e7c911db024..db433bee87af 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -70,7 +70,6 @@ struct wfx_vif { int id; enum wfx_state state; - int delayed_link_loss; int bss_loss_state; u32 bss_loss_confirm_id; struct mutex bss_loss_lock; From 4337074be76d853e3677461dd19bd7c1759c55f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:41 +0000 Subject: [PATCH 154/353] staging: wfx: implement cancel_hw_scan() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The device provides an API to abort a scan request. Expose this feature to mac80211. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-55-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/main.c | 1 + drivers/staging/wfx/scan.c | 13 +++++++++++++ drivers/staging/wfx/scan.h | 1 + drivers/staging/wfx/wfx.h | 1 + 4 files changed, 16 insertions(+) diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c index cf4bcb14a12d..45c9939b7e62 100644 --- a/drivers/staging/wfx/main.c +++ b/drivers/staging/wfx/main.c @@ -135,6 +135,7 @@ static const struct ieee80211_ops wfx_ops = { .tx = wfx_tx, .conf_tx = wfx_conf_tx, .hw_scan = wfx_hw_scan, + .cancel_hw_scan = wfx_cancel_hw_scan, .sta_add = wfx_sta_add, .sta_remove = wfx_sta_remove, .sta_notify = wfx_sta_notify, diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index dde2f8868147..24061d09c404 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -54,6 +54,7 @@ static int send_scan_req(struct wfx_vif *wvif, break; } wfx_tx_lock_flush(wvif->wdev); + wvif->scan_abort = false; reinit_completion(&wvif->scan_complete); ret = hif_scan(wvif, req, start_idx, i - start_idx); if (ret < 0) @@ -68,6 +69,10 @@ static int send_scan_req(struct wfx_vif *wvif, hif_stop_scan(wvif); return -ETIMEDOUT; } + if (wvif->scan_abort) { + dev_notice(wvif->wdev->dev, "scan abort\n"); + return -ECONNABORTED; + } return i - start_idx; } @@ -115,6 +120,14 @@ int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return 0; } +void wfx_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv; + + wvif->scan_abort = true; + hif_stop_scan(wvif); +} + void wfx_scan_complete(struct wfx_vif *wvif, const struct hif_ind_scan_cmpl *arg) { diff --git a/drivers/staging/wfx/scan.h b/drivers/staging/wfx/scan.h index b547f1927d72..bba9f15a9ff5 100644 --- a/drivers/staging/wfx/scan.h +++ b/drivers/staging/wfx/scan.h @@ -18,6 +18,7 @@ struct wfx_vif; void wfx_hw_scan_work(struct work_struct *work); int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *req); +void wfx_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void wfx_scan_complete(struct wfx_vif *wvif, const struct hif_ind_scan_cmpl *ind); diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index db433bee87af..0a3df382af03 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -127,6 +127,7 @@ struct wfx_vif { struct mutex scan_lock; struct work_struct scan_work; struct completion scan_complete; + bool scan_abort; struct ieee80211_scan_request *scan_req; struct completion set_pm_mode_complete; From 6db45b06611ce8ebae6952e249257bd45d980ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Tue, 17 Dec 2019 16:15:42 +0000 Subject: [PATCH 155/353] staging: wfx: update TODO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the TODO list of wfx driver with a more precise list of items. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20191217161318.31402-56-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/TODO | 79 +++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 13 deletions(-) diff --git a/drivers/staging/wfx/TODO b/drivers/staging/wfx/TODO index e44772289af8..6b1cdd24afc9 100644 --- a/drivers/staging/wfx/TODO +++ b/drivers/staging/wfx/TODO @@ -1,17 +1,70 @@ This is a list of things that need to be done to get this driver out of the staging directory. - - I have to take a decision about secure link support. I can: - - drop completely - - keep it in an external patch (my preferred option) - - replace call to mbedtls with kernel crypto API (necessitate a - bunch of work) - - pull mbedtls in kernel (non-realistic) + - Allocation of "link ids" is too complex. Allocation/release of link ids from + sta_add()/sta_remove() should be sufficient. - - mac80211 interface does not (yet) have expected quality to be placed - outside of staging: - - Some processings are redundant with mac80211 ones - - Many members from wfx_dev/wfx_vif can be retrieved from mac80211 - structures - - Some functions are too complex - - ... + - The path for packets with IEEE80211_TX_CTL_SEND_AFTER_DTIM flags should be + cleaned up. Currently, the process involve multiple work structs and a + timer. It could be simplifed. In add, the requeue mechanism triggers more + frequently than it should. + + - All structures defined in hif_api_*.h are intended to sent/received to/from + hardware. All their members whould be declared __le32 or __le16. These + structs should only been used in files named hif_* (and maybe in data_*.c). + The upper layers (sta.c, scan.c etc...) should manage mac80211 structures. + See: + https://lore.kernel.org/lkml/20191111202852.GX26530@ZenIV.linux.org.uk + + - Once previous item done, it will be possible to audit the driver with + `sparse'. It will probably find tons of problems with big endian + architectures. + + - hif_api_*.h whave been imported from firmware code. Some of the structures + are never used in driver. + + - Driver try to maintains power save status of the stations. However, this + work is already done by mac80211. sta_asleep_mask and pspoll_mask should be + dropped. + + - wfx_tx_queues_get() should be reworked. It currently try compute itself the + QoS policy. However, firmware already do the job. Firmware would prefer to + have a few packets in each queue and be able to choose itself which queue to + use. + + - As suggested by Felix, rate control could be improved following this idea: + https://lore.kernel.org/lkml/3099559.gv3Q75KnN1@pc-42/ + + - When driver is about to loose BSS, it forge its own Null Func request (see + wfx_cqm_bssloss_sm()). It should use mechanism provided by mac80211. + + - AP is actually is setup after a call to wfx_bss_info_changed(). Yet, + ieee80211_ops provide callback start_ap(). + + - The current process for joining a network is incredibly complex. Should be + reworked. + + - Monitoring mode is not implemented despite being mandatory by mac80211. + + - "compatible" value are not correct. They should be "vendor,chip". See: + https://lore.kernel.org/driverdev-devel/5226570.CMH5hVlZcI@pc-42 + + - The "state" field from wfx_vif should be replaced by "vif->type". + + - It seems that wfx_upload_keys() is useless. + + - "event_queue" from wfx_vif seems overkill. These event are rare and they + probably could be handled in a simpler fashion. + + - Feature called "secure link" should be either developed (using kernel + crypto API) or dropped. + + - In wfx_cmd_send(), "async" allow to send command without waiting the reply. + It may help in some situation, but it is not yet used. In add, it may cause + some trouble: + https://lore.kernel.org/driverdev-devel/alpine.DEB.2.21.1910041317381.2992@hadrien/ + So, fix it (by replacing the mutex with a semaphore) or drop it. + + - Chip support P2P, but driver does not implement it. + + - Chip support kind of Mesh, but driver does not implement it. From a5a98554206651b25d84a25b49eeac31dffbe358 Mon Sep 17 00:00:00 2001 From: Xidong Wang Date: Wed, 18 Dec 2019 13:56:38 +0800 Subject: [PATCH 156/353] staging: nvec: check return value In nvec_kbd_probe(), the return value of devm_input_allocate_device() should be checked before it is used. Signed-off-by: Xidong Wang Link: https://lore.kernel.org/r/1576648598-12257-1-git-send-email-wangxidong_97@163.com Acked-by: Marc Dietrich Signed-off-by: Greg Kroah-Hartman --- drivers/staging/nvec/nvec_kbd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/nvec/nvec_kbd.c b/drivers/staging/nvec/nvec_kbd.c index 01dbb66f7e9a..386d619e3ee9 100644 --- a/drivers/staging/nvec/nvec_kbd.c +++ b/drivers/staging/nvec/nvec_kbd.c @@ -123,6 +123,8 @@ static int nvec_kbd_probe(struct platform_device *pdev) keycodes[j++] = extcode_tab_us102[i]; idev = devm_input_allocate_device(&pdev->dev); + if (!idev) + return -ENOMEM; idev->name = "nvec keyboard"; idev->phys = "nvec"; idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_LED); From 5264c5f4c4690658922fcaddc1cdd925fb0069fd Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Fri, 20 Dec 2019 16:00:49 +0000 Subject: [PATCH 157/353] dt-bindings: iio: accel: bma400: add bindings Add devicetree binding for the Bosch BMA400 3-axes ultra-low power accelerometer sensor. Signed-off-by: Dan Robertson Reviewed-by: Linus Walleij Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/accel/bosch,bma400.yaml | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml diff --git a/Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml b/Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml new file mode 100644 index 000000000000..c1c6d6f223cf --- /dev/null +++ b/Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/accel/bosch,bma400.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Bosch BMA400 triaxial acceleration sensor + +maintainers: + - Dan Robertson + +description: | + Acceleration and temperature iio sensors with an i2c interface + + Specifications about the sensor can be found at: + https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMA400-DS000.pdf + +properties: + compatible: + enum: + - bosch,bma400 + + reg: + maxItems: 1 + + vdd-supply: + description: phandle to the regulator that provides power to the accelerometer + + vddio-supply: + description: phandle to the regulator that provides power to the sensor's IO + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + +examples: + - | + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + accelerometer@14 { + compatible = "bosch,bma400"; + reg = <0x14>; + vdd-supply = <&vdd>; + vddio-supply = <&vddio>; + interrupt-parent = <&gpio0>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + }; + }; From 465c811f1f201a7554a95cf003bc06a239606e9b Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Fri, 20 Dec 2019 16:00:50 +0000 Subject: [PATCH 158/353] iio: accel: Add driver for the BMA400 Add a IIO driver for the Bosch BMA400 3-axes ultra-low power accelerometer. The driver supports reading from the acceleration and temperature registers. The driver also supports reading and configuring the output data rate, oversampling ratio, and scale. Signed-off-by: Dan Robertson Reviewed-by: Andy Shevchenko Reviewed-by: Linus Walleij Signed-off-by: Jonathan Cameron --- MAINTAINERS | 7 + drivers/iio/accel/Kconfig | 16 + drivers/iio/accel/Makefile | 2 + drivers/iio/accel/bma400.h | 95 ++++ drivers/iio/accel/bma400_core.c | 823 ++++++++++++++++++++++++++++++++ drivers/iio/accel/bma400_i2c.c | 61 +++ 6 files changed, 1004 insertions(+) create mode 100644 drivers/iio/accel/bma400.h create mode 100644 drivers/iio/accel/bma400_core.c create mode 100644 drivers/iio/accel/bma400_i2c.c diff --git a/MAINTAINERS b/MAINTAINERS index 896951d11e50..ee36c19eca1b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3064,6 +3064,13 @@ S: Supported F: drivers/net/bonding/ F: include/uapi/linux/if_bonding.h +BOSCH SENSORTEC BMA400 ACCELEROMETER IIO DRIVER +M: Dan Robertson +L: linux-iio@vger.kernel.org +S: Maintained +F: drivers/iio/accel/bma400* +F: Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml + BPF (Safe dynamic programs and tools) M: Alexei Starovoitov M: Daniel Borkmann diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index d4ef35aeb579..670e60568033 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -112,6 +112,22 @@ config BMA220 To compile this driver as a module, choose M here: the module will be called bma220_spi. +config BMA400 + tristate "Bosch BMA400 3-Axis Accelerometer Driver" + select REGMAP + select BMA400_I2C if I2C + help + Say Y here if you want to build a driver for the Bosch BMA400 + triaxial acceleration sensor. + + To compile this driver as a module, choose M here: the + module will be called bma400_core and you will also get + bma400_i2c if I2C is enabled. + +config BMA400_I2C + tristate + depends on BMA400 + config BMC150_ACCEL tristate "Bosch BMC150 Accelerometer Driver" select IIO_BUFFER diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 56bd0215e0d4..3a051cf37f40 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -14,6 +14,8 @@ obj-$(CONFIG_ADXL372_I2C) += adxl372_i2c.o obj-$(CONFIG_ADXL372_SPI) += adxl372_spi.o obj-$(CONFIG_BMA180) += bma180.o obj-$(CONFIG_BMA220) += bma220_spi.o +obj-$(CONFIG_BMA400) += bma400_core.o +obj-$(CONFIG_BMA400_I2C) += bma400_i2c.o obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h new file mode 100644 index 000000000000..15c0e307d2c4 --- /dev/null +++ b/drivers/iio/accel/bma400.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Register constants and other forward declarations needed by the bma400 + * sources. + * + * Copyright 2019 Dan Robertson + */ + +#ifndef _BMA400_H_ +#define _BMA400_H_ + +#include +#include + +/* + * Read-Only Registers + */ + +/* Status and ID registers */ +#define BMA400_CHIP_ID_REG 0x00 +#define BMA400_ERR_REG 0x02 +#define BMA400_STATUS_REG 0x03 + +/* Acceleration registers */ +#define BMA400_X_AXIS_LSB_REG 0x04 +#define BMA400_X_AXIS_MSB_REG 0x05 +#define BMA400_Y_AXIS_LSB_REG 0x06 +#define BMA400_Y_AXIS_MSB_REG 0x07 +#define BMA400_Z_AXIS_LSB_REG 0x08 +#define BMA400_Z_AXIS_MSB_REG 0x09 + +/* Sensor time registers */ +#define BMA400_SENSOR_TIME0 0x0a +#define BMA400_SENSOR_TIME1 0x0b +#define BMA400_SENSOR_TIME2 0x0c + +/* Event and interrupt registers */ +#define BMA400_EVENT_REG 0x0d +#define BMA400_INT_STAT0_REG 0x0e +#define BMA400_INT_STAT1_REG 0x0f +#define BMA400_INT_STAT2_REG 0x10 + +/* Temperature register */ +#define BMA400_TEMP_DATA_REG 0x11 + +/* FIFO length and data registers */ +#define BMA400_FIFO_LENGTH0_REG 0x12 +#define BMA400_FIFO_LENGTH1_REG 0x13 +#define BMA400_FIFO_DATA_REG 0x14 + +/* Step count registers */ +#define BMA400_STEP_CNT0_REG 0x15 +#define BMA400_STEP_CNT1_REG 0x16 +#define BMA400_STEP_CNT3_REG 0x17 +#define BMA400_STEP_STAT_REG 0x18 + +/* + * Read-write configuration registers + */ +#define BMA400_ACC_CONFIG0_REG 0x19 +#define BMA400_ACC_CONFIG1_REG 0x1a +#define BMA400_ACC_CONFIG2_REG 0x1b +#define BMA400_CMD_REG 0x7e + +/* Chip ID of BMA 400 devices found in the chip ID register. */ +#define BMA400_ID_REG_VAL 0x90 + +#define BMA400_LP_OSR_SHIFT 5 +#define BMA400_NP_OSR_SHIFT 4 +#define BMA400_SCALE_SHIFT 6 + +#define BMA400_TWO_BITS_MASK GENMASK(1, 0) +#define BMA400_LP_OSR_MASK GENMASK(6, 5) +#define BMA400_NP_OSR_MASK GENMASK(5, 4) +#define BMA400_ACC_ODR_MASK GENMASK(3, 0) +#define BMA400_ACC_SCALE_MASK GENMASK(7, 6) + +#define BMA400_ACC_ODR_MIN_RAW 0x05 +#define BMA400_ACC_ODR_LP_RAW 0x06 +#define BMA400_ACC_ODR_MAX_RAW 0x0b + +#define BMA400_ACC_ODR_MAX_HZ 800 +#define BMA400_ACC_ODR_MIN_WHOLE_HZ 25 +#define BMA400_ACC_ODR_MIN_HZ 12 + +#define BMA400_SCALE_MIN 38357 +#define BMA400_SCALE_MAX 306864 + +extern const struct regmap_config bma400_regmap_config; + +int bma400_probe(struct device *dev, struct regmap *regmap, const char *name); + +int bma400_remove(struct device *dev); + +#endif diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c new file mode 100644 index 000000000000..b0a31294c09e --- /dev/null +++ b/drivers/iio/accel/bma400_core.c @@ -0,0 +1,823 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Core IIO driver for Bosch BMA400 triaxial acceleration sensor. + * + * Copyright 2019 Dan Robertson + * + * TODO: + * - Support for power management + * - Support events and interrupts + * - Create channel for step count + * - Create channel for sensor time + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bma400.h" + +/* + * The G-range selection may be one of 2g, 4g, 8, or 16g. The scale may + * be selected with the acc_range bits of the ACC_CONFIG1 register. + * NB: This buffer is populated in the device init. + */ +static int bma400_scales[8]; + +/* + * See the ACC_CONFIG1 section of the datasheet. + * NB: This buffer is populated in the device init. + */ +static int bma400_sample_freqs[14]; + +static const int bma400_osr_range[] = { 0, 1, 3 }; + +/* See the ACC_CONFIG0 section of the datasheet */ +enum bma400_power_mode { + POWER_MODE_SLEEP = 0x00, + POWER_MODE_LOW = 0x01, + POWER_MODE_NORMAL = 0x02, + POWER_MODE_INVALID = 0x03, +}; + +struct bma400_sample_freq { + int hz; + int uhz; +}; + +struct bma400_data { + struct device *dev; + struct regmap *regmap; + struct mutex mutex; /* data register lock */ + struct iio_mount_matrix orientation; + enum bma400_power_mode power_mode; + struct bma400_sample_freq sample_freq; + int oversampling_ratio; + int scale; +}; + +static bool bma400_is_writable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BMA400_CHIP_ID_REG: + case BMA400_ERR_REG: + case BMA400_STATUS_REG: + case BMA400_X_AXIS_LSB_REG: + case BMA400_X_AXIS_MSB_REG: + case BMA400_Y_AXIS_LSB_REG: + case BMA400_Y_AXIS_MSB_REG: + case BMA400_Z_AXIS_LSB_REG: + case BMA400_Z_AXIS_MSB_REG: + case BMA400_SENSOR_TIME0: + case BMA400_SENSOR_TIME1: + case BMA400_SENSOR_TIME2: + case BMA400_EVENT_REG: + case BMA400_INT_STAT0_REG: + case BMA400_INT_STAT1_REG: + case BMA400_INT_STAT2_REG: + case BMA400_TEMP_DATA_REG: + case BMA400_FIFO_LENGTH0_REG: + case BMA400_FIFO_LENGTH1_REG: + case BMA400_FIFO_DATA_REG: + case BMA400_STEP_CNT0_REG: + case BMA400_STEP_CNT1_REG: + case BMA400_STEP_CNT3_REG: + case BMA400_STEP_STAT_REG: + return false; + default: + return true; + } +} + +static bool bma400_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case BMA400_ERR_REG: + case BMA400_STATUS_REG: + case BMA400_X_AXIS_LSB_REG: + case BMA400_X_AXIS_MSB_REG: + case BMA400_Y_AXIS_LSB_REG: + case BMA400_Y_AXIS_MSB_REG: + case BMA400_Z_AXIS_LSB_REG: + case BMA400_Z_AXIS_MSB_REG: + case BMA400_SENSOR_TIME0: + case BMA400_SENSOR_TIME1: + case BMA400_SENSOR_TIME2: + case BMA400_EVENT_REG: + case BMA400_INT_STAT0_REG: + case BMA400_INT_STAT1_REG: + case BMA400_INT_STAT2_REG: + case BMA400_TEMP_DATA_REG: + case BMA400_FIFO_LENGTH0_REG: + case BMA400_FIFO_LENGTH1_REG: + case BMA400_FIFO_DATA_REG: + case BMA400_STEP_CNT0_REG: + case BMA400_STEP_CNT1_REG: + case BMA400_STEP_CNT3_REG: + case BMA400_STEP_STAT_REG: + return true; + default: + return false; + } +} + +const struct regmap_config bma400_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = BMA400_CMD_REG, + .cache_type = REGCACHE_RBTREE, + .writeable_reg = bma400_is_writable_reg, + .volatile_reg = bma400_is_volatile_reg, +}; +EXPORT_SYMBOL(bma400_regmap_config); + +static const struct iio_mount_matrix * +bma400_accel_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct bma400_data *data = iio_priv(indio_dev); + + return &data->orientation; +} + +static const struct iio_chan_spec_ext_info bma400_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bma400_accel_get_mount_matrix), + { } +}; + +#define BMA400_ACC_CHANNEL(_axis) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = IIO_MOD_##_axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .ext_info = bma400_ext_info, \ +} + +static const struct iio_chan_spec bma400_channels[] = { + BMA400_ACC_CHANNEL(X), + BMA400_ACC_CHANNEL(Y), + BMA400_ACC_CHANNEL(Z), + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), + }, +}; + +static int bma400_get_temp_reg(struct bma400_data *data, int *val, int *val2) +{ + unsigned int raw_temp; + int host_temp; + int ret; + + if (data->power_mode == POWER_MODE_SLEEP) + return -EBUSY; + + ret = regmap_read(data->regmap, BMA400_TEMP_DATA_REG, &raw_temp); + if (ret) + return ret; + + host_temp = sign_extend32(raw_temp, 7); + /* + * The formula for the TEMP_DATA register in the datasheet + * is: x * 0.5 + 23 + */ + *val = (host_temp >> 1) + 23; + *val2 = (host_temp & 0x1) * 500000; + return IIO_VAL_INT_PLUS_MICRO; +} + +static int bma400_get_accel_reg(struct bma400_data *data, + const struct iio_chan_spec *chan, + int *val) +{ + __le16 raw_accel; + int lsb_reg; + int ret; + + if (data->power_mode == POWER_MODE_SLEEP) + return -EBUSY; + + switch (chan->channel2) { + case IIO_MOD_X: + lsb_reg = BMA400_X_AXIS_LSB_REG; + break; + case IIO_MOD_Y: + lsb_reg = BMA400_Y_AXIS_LSB_REG; + break; + case IIO_MOD_Z: + lsb_reg = BMA400_Z_AXIS_LSB_REG; + break; + default: + dev_err(data->dev, "invalid axis channel modifier\n"); + return -EINVAL; + } + + /* bulk read two registers, with the base being the LSB register */ + ret = regmap_bulk_read(data->regmap, lsb_reg, &raw_accel, + sizeof(raw_accel)); + if (ret) + return ret; + + *val = sign_extend32(le16_to_cpu(raw_accel), 11); + return IIO_VAL_INT; +} + +static void bma400_output_data_rate_from_raw(int raw, unsigned int *val, + unsigned int *val2) +{ + *val = BMA400_ACC_ODR_MAX_HZ >> (BMA400_ACC_ODR_MAX_RAW - raw); + if (raw > BMA400_ACC_ODR_MIN_RAW) + *val2 = 0; + else + *val2 = 500000; +} + +static int bma400_get_accel_output_data_rate(struct bma400_data *data) +{ + unsigned int val; + unsigned int odr; + int ret; + + switch (data->power_mode) { + case POWER_MODE_LOW: + /* + * Runs at a fixed rate in low-power mode. See section 4.3 + * in the datasheet. + */ + bma400_output_data_rate_from_raw(BMA400_ACC_ODR_LP_RAW, + &data->sample_freq.hz, + &data->sample_freq.uhz); + return 0; + case POWER_MODE_NORMAL: + /* + * In normal mode the ODR can be found in the ACC_CONFIG1 + * register. + */ + ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG, &val); + if (ret) + goto error; + + odr = val & BMA400_ACC_ODR_MASK; + if (odr < BMA400_ACC_ODR_MIN_RAW || + odr > BMA400_ACC_ODR_MAX_RAW) { + ret = -EINVAL; + goto error; + } + + bma400_output_data_rate_from_raw(odr, &data->sample_freq.hz, + &data->sample_freq.uhz); + return 0; + case POWER_MODE_SLEEP: + data->sample_freq.hz = 0; + data->sample_freq.uhz = 0; + return 0; + default: + ret = 0; + goto error; + } +error: + data->sample_freq.hz = -1; + data->sample_freq.uhz = -1; + return ret; +} + +static int bma400_set_accel_output_data_rate(struct bma400_data *data, + int hz, int uhz) +{ + unsigned int idx; + unsigned int odr; + unsigned int val; + int ret; + + if (hz >= BMA400_ACC_ODR_MIN_WHOLE_HZ) { + if (uhz || hz > BMA400_ACC_ODR_MAX_HZ) + return -EINVAL; + + /* Note this works because MIN_WHOLE_HZ is odd */ + idx = __ffs(hz); + + if (hz >> idx != BMA400_ACC_ODR_MIN_WHOLE_HZ) + return -EINVAL; + + idx += BMA400_ACC_ODR_MIN_RAW + 1; + } else if (hz == BMA400_ACC_ODR_MIN_HZ && uhz == 500000) { + idx = BMA400_ACC_ODR_MIN_RAW; + } else { + return -EINVAL; + } + + ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG, &val); + if (ret) + return ret; + + /* preserve the range and normal mode osr */ + odr = (~BMA400_ACC_ODR_MASK & val) | idx; + + ret = regmap_write(data->regmap, BMA400_ACC_CONFIG1_REG, odr); + if (ret) + return ret; + + bma400_output_data_rate_from_raw(idx, &data->sample_freq.hz, + &data->sample_freq.uhz); + return 0; +} + +static int bma400_get_accel_oversampling_ratio(struct bma400_data *data) +{ + unsigned int val; + unsigned int osr; + int ret; + + /* + * The oversampling ratio is stored in a different register + * based on the power-mode. In normal mode the OSR is stored + * in ACC_CONFIG1. In low-power mode it is stored in + * ACC_CONFIG0. + */ + switch (data->power_mode) { + case POWER_MODE_LOW: + ret = regmap_read(data->regmap, BMA400_ACC_CONFIG0_REG, &val); + if (ret) { + data->oversampling_ratio = -1; + return ret; + } + + osr = (val & BMA400_LP_OSR_MASK) >> BMA400_LP_OSR_SHIFT; + + data->oversampling_ratio = osr; + return 0; + case POWER_MODE_NORMAL: + ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG, &val); + if (ret) { + data->oversampling_ratio = -1; + return ret; + } + + osr = (val & BMA400_NP_OSR_MASK) >> BMA400_NP_OSR_SHIFT; + + data->oversampling_ratio = osr; + return 0; + case POWER_MODE_SLEEP: + data->oversampling_ratio = 0; + return 0; + default: + data->oversampling_ratio = -1; + return -EINVAL; + } +} + +static int bma400_set_accel_oversampling_ratio(struct bma400_data *data, + int val) +{ + unsigned int acc_config; + int ret; + + if (val & ~BMA400_TWO_BITS_MASK) + return -EINVAL; + + /* + * The oversampling ratio is stored in a different register + * based on the power-mode. + */ + switch (data->power_mode) { + case POWER_MODE_LOW: + ret = regmap_read(data->regmap, BMA400_ACC_CONFIG0_REG, + &acc_config); + if (ret) + return ret; + + ret = regmap_write(data->regmap, BMA400_ACC_CONFIG0_REG, + (acc_config & ~BMA400_LP_OSR_MASK) | + (val << BMA400_LP_OSR_SHIFT)); + if (ret) { + dev_err(data->dev, "Failed to write out OSR\n"); + return ret; + } + + data->oversampling_ratio = val; + return 0; + case POWER_MODE_NORMAL: + ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG, + &acc_config); + if (ret) + return ret; + + ret = regmap_write(data->regmap, BMA400_ACC_CONFIG1_REG, + (acc_config & ~BMA400_NP_OSR_MASK) | + (val << BMA400_NP_OSR_SHIFT)); + if (ret) { + dev_err(data->dev, "Failed to write out OSR\n"); + return ret; + } + + data->oversampling_ratio = val; + return 0; + default: + return -EINVAL; + } + return ret; +} + +static int bma400_accel_scale_to_raw(struct bma400_data *data, + unsigned int val) +{ + int raw; + + if (val == 0) + return -EINVAL; + + /* Note this works because BMA400_SCALE_MIN is odd */ + raw = __ffs(val); + + if (val >> raw != BMA400_SCALE_MIN) + return -EINVAL; + + return raw; +} + +static int bma400_get_accel_scale(struct bma400_data *data) +{ + unsigned int raw_scale; + unsigned int val; + int ret; + + ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG, &val); + if (ret) + return ret; + + raw_scale = (val & BMA400_ACC_SCALE_MASK) >> BMA400_SCALE_SHIFT; + if (raw_scale > BMA400_TWO_BITS_MASK) + return -EINVAL; + + data->scale = BMA400_SCALE_MIN << raw_scale; + + return 0; +} + +static int bma400_set_accel_scale(struct bma400_data *data, unsigned int val) +{ + unsigned int acc_config; + int raw; + int ret; + + ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG, &acc_config); + if (ret) + return ret; + + raw = bma400_accel_scale_to_raw(data, val); + if (raw < 0) + return raw; + + ret = regmap_write(data->regmap, BMA400_ACC_CONFIG1_REG, + (acc_config & ~BMA400_ACC_SCALE_MASK) | + (raw << BMA400_SCALE_SHIFT)); + if (ret) + return ret; + + data->scale = val; + return 0; +} + +static int bma400_get_power_mode(struct bma400_data *data) +{ + unsigned int val; + int ret; + + ret = regmap_read(data->regmap, BMA400_STATUS_REG, &val); + if (ret) { + dev_err(data->dev, "Failed to read status register\n"); + return ret; + } + + data->power_mode = (val >> 1) & BMA400_TWO_BITS_MASK; + return 0; +} + +static int bma400_set_power_mode(struct bma400_data *data, + enum bma400_power_mode mode) +{ + unsigned int val; + int ret; + + ret = regmap_read(data->regmap, BMA400_ACC_CONFIG0_REG, &val); + if (ret) + return ret; + + if (data->power_mode == mode) + return 0; + + if (mode == POWER_MODE_INVALID) + return -EINVAL; + + /* Preserve the low-power oversample ratio etc */ + ret = regmap_write(data->regmap, BMA400_ACC_CONFIG0_REG, + mode | (val & ~BMA400_TWO_BITS_MASK)); + if (ret) { + dev_err(data->dev, "Failed to write to power-mode\n"); + return ret; + } + + data->power_mode = mode; + + /* + * Update our cached osr and odr based on the new + * power-mode. + */ + bma400_get_accel_output_data_rate(data); + bma400_get_accel_oversampling_ratio(data); + return 0; +} + +static void bma400_init_tables(void) +{ + int raw; + int i; + + for (i = 0; i + 1 < ARRAY_SIZE(bma400_sample_freqs); i += 2) { + raw = (i / 2) + 5; + bma400_output_data_rate_from_raw(raw, &bma400_sample_freqs[i], + &bma400_sample_freqs[i + 1]); + } + + for (i = 0; i + 1 < ARRAY_SIZE(bma400_scales); i += 2) { + raw = i / 2; + bma400_scales[i] = 0; + bma400_scales[i + 1] = BMA400_SCALE_MIN << raw; + } +} + +static int bma400_init(struct bma400_data *data) +{ + unsigned int val; + int ret; + + /* Try to read chip_id register. It must return 0x90. */ + ret = regmap_read(data->regmap, BMA400_CHIP_ID_REG, &val); + if (ret) { + dev_err(data->dev, "Failed to read chip id register\n"); + goto out; + } + + if (val != BMA400_ID_REG_VAL) { + dev_err(data->dev, "Chip ID mismatch\n"); + ret = -ENODEV; + goto out; + } + + ret = bma400_get_power_mode(data); + if (ret) { + dev_err(data->dev, "Failed to get the initial power-mode\n"); + goto out; + } + + if (data->power_mode != POWER_MODE_NORMAL) { + ret = bma400_set_power_mode(data, POWER_MODE_NORMAL); + if (ret) { + dev_err(data->dev, "Failed to wake up the device\n"); + goto out; + } + /* + * TODO: The datasheet waits 1500us here in the example, but + * lists 2/ODR as the wakeup time. + */ + usleep_range(1500, 2000); + } + + bma400_init_tables(); + + ret = bma400_get_accel_output_data_rate(data); + if (ret) + goto out; + + ret = bma400_get_accel_oversampling_ratio(data); + if (ret) + goto out; + + ret = bma400_get_accel_scale(data); + if (ret) + goto out; + + /* + * Once the interrupt engine is supported we might use the + * data_src_reg, but for now ensure this is set to the + * variable ODR filter selectable by the sample frequency + * channel. + */ + return regmap_write(data->regmap, BMA400_ACC_CONFIG2_REG, 0x00); + +out: + return ret; +} + +static int bma400_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct bma400_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + mutex_lock(&data->mutex); + ret = bma400_get_temp_reg(data, val, val2); + mutex_unlock(&data->mutex); + return ret; + case IIO_CHAN_INFO_RAW: + mutex_lock(&data->mutex); + ret = bma400_get_accel_reg(data, chan, val); + mutex_unlock(&data->mutex); + return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + switch (chan->type) { + case IIO_ACCEL: + if (data->sample_freq.hz < 0) + return -EINVAL; + + *val = data->sample_freq.hz; + *val2 = data->sample_freq.uhz; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_TEMP: + /* + * Runs at a fixed sampling frequency. See Section 4.4 + * of the datasheet. + */ + *val = 6; + *val2 = 250000; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = data->scale; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + /* + * TODO: We could avoid this logic and returning -EINVAL here if + * we set both the low-power and normal mode OSR registers when + * we configure the device. + */ + if (data->oversampling_ratio < 0) + return -EINVAL; + + *val = data->oversampling_ratio; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int bma400_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + *type = IIO_VAL_INT_PLUS_MICRO; + *vals = bma400_scales; + *length = ARRAY_SIZE(bma400_scales); + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *type = IIO_VAL_INT; + *vals = bma400_osr_range; + *length = ARRAY_SIZE(bma400_osr_range); + return IIO_AVAIL_RANGE; + case IIO_CHAN_INFO_SAMP_FREQ: + *type = IIO_VAL_INT_PLUS_MICRO; + *vals = bma400_sample_freqs; + *length = ARRAY_SIZE(bma400_sample_freqs); + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static int bma400_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, + long mask) +{ + struct bma400_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + /* + * The sample frequency is readonly for the temperature + * register and a fixed value in low-power mode. + */ + if (chan->type != IIO_ACCEL) + return -EINVAL; + + mutex_lock(&data->mutex); + ret = bma400_set_accel_output_data_rate(data, val, val2); + mutex_unlock(&data->mutex); + return ret; + case IIO_CHAN_INFO_SCALE: + if (val != 0 || val2 > BMA400_SCALE_MAX) + return -EINVAL; + + mutex_lock(&data->mutex); + ret = bma400_set_accel_scale(data, val2); + mutex_unlock(&data->mutex); + return ret; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + mutex_lock(&data->mutex); + ret = bma400_set_accel_oversampling_ratio(data, val); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } +} + +static int bma400_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static const struct iio_info bma400_info = { + .read_raw = bma400_read_raw, + .read_avail = bma400_read_avail, + .write_raw = bma400_write_raw, + .write_raw_get_fmt = bma400_write_raw_get_fmt, +}; + +int bma400_probe(struct device *dev, struct regmap *regmap, const char *name) +{ + struct iio_dev *indio_dev; + struct bma400_data *data; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->regmap = regmap; + data->dev = dev; + + ret = bma400_init(data); + if (ret) + return ret; + + ret = iio_read_mount_matrix(dev, "mount-matrix", &data->orientation); + if (ret) + return ret; + + mutex_init(&data->mutex); + indio_dev->dev.parent = dev; + indio_dev->name = name; + indio_dev->info = &bma400_info; + indio_dev->channels = bma400_channels; + indio_dev->num_channels = ARRAY_SIZE(bma400_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + dev_set_drvdata(dev, indio_dev); + + return iio_device_register(indio_dev); +} +EXPORT_SYMBOL(bma400_probe); + +int bma400_remove(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct bma400_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->mutex); + ret = bma400_set_power_mode(data, POWER_MODE_SLEEP); + mutex_unlock(&data->mutex); + + iio_device_unregister(indio_dev); + + return ret; +} +EXPORT_SYMBOL(bma400_remove); + +MODULE_AUTHOR("Dan Robertson "); +MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor core"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/accel/bma400_i2c.c b/drivers/iio/accel/bma400_i2c.c new file mode 100644 index 000000000000..9dcb7cc9996e --- /dev/null +++ b/drivers/iio/accel/bma400_i2c.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * I2C IIO driver for Bosch BMA400 triaxial acceleration sensor. + * + * Copyright 2019 Dan Robertson + * + * I2C address is either 0x14 or 0x15 depending on SDO + */ +#include +#include +#include +#include + +#include "bma400.h" + +static int bma400_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_i2c(client, &bma400_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "failed to create regmap\n"); + return PTR_ERR(regmap); + } + + return bma400_probe(&client->dev, regmap, id->name); +} + +static int bma400_i2c_remove(struct i2c_client *client) +{ + return bma400_remove(&client->dev); +} + +static const struct i2c_device_id bma400_i2c_ids[] = { + { "bma400", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, bma400_i2c_ids); + +static const struct of_device_id bma400_of_i2c_match[] = { + { .compatible = "bosch,bma400" }, + { } +}; +MODULE_DEVICE_TABLE(of, bma400_of_i2c_match); + +static struct i2c_driver bma400_i2c_driver = { + .driver = { + .name = "bma400", + .of_match_table = bma400_of_i2c_match, + }, + .probe = bma400_i2c_probe, + .remove = bma400_i2c_remove, + .id_table = bma400_i2c_ids, +}; + +module_i2c_driver(bma400_i2c_driver); + +MODULE_AUTHOR("Dan Robertson "); +MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor (I2C)"); +MODULE_LICENSE("GPL"); From 3cf7ded15e404655d4bcdcac76e0fe2247946d05 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Fri, 20 Dec 2019 16:00:51 +0000 Subject: [PATCH 159/353] iio: accel: bma400: basic regulator support Add support for the VDD and VDDIO regulators using the regulator framework. Signed-off-by: Dan Robertson Reviewed-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma400.h | 4 ++++ drivers/iio/accel/bma400_core.c | 39 ++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h index 15c0e307d2c4..5ad10db9819f 100644 --- a/drivers/iio/accel/bma400.h +++ b/drivers/iio/accel/bma400.h @@ -86,6 +86,10 @@ #define BMA400_SCALE_MIN 38357 #define BMA400_SCALE_MAX 306864 +#define BMA400_NUM_REGULATORS 2 +#define BMA400_VDD_REGULATOR 0 +#define BMA400_VDDIO_REGULATOR 1 + extern const struct regmap_config bma400_regmap_config; int bma400_probe(struct device *dev, struct regmap *regmap, const char *name); diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c index b0a31294c09e..ab4a158b35af 100644 --- a/drivers/iio/accel/bma400_core.c +++ b/drivers/iio/accel/bma400_core.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "bma400.h" @@ -53,6 +54,7 @@ struct bma400_sample_freq { struct bma400_data { struct device *dev; struct regmap *regmap; + struct regulator_bulk_data regulators[BMA400_NUM_REGULATORS]; struct mutex mutex; /* data register lock */ struct iio_mount_matrix orientation; enum bma400_power_mode power_mode; @@ -576,17 +578,38 @@ static int bma400_init(struct bma400_data *data) goto out; } + data->regulators[BMA400_VDD_REGULATOR].supply = "vdd"; + data->regulators[BMA400_VDDIO_REGULATOR].supply = "vddio"; + ret = devm_regulator_bulk_get(data->dev, + ARRAY_SIZE(data->regulators), + data->regulators); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(data->dev, + "Failed to get regulators: %d\n", + ret); + + goto out; + } + ret = regulator_bulk_enable(ARRAY_SIZE(data->regulators), + data->regulators); + if (ret) { + dev_err(data->dev, "Failed to enable regulators: %d\n", + ret); + goto out; + } + ret = bma400_get_power_mode(data); if (ret) { dev_err(data->dev, "Failed to get the initial power-mode\n"); - goto out; + goto err_reg_disable; } if (data->power_mode != POWER_MODE_NORMAL) { ret = bma400_set_power_mode(data, POWER_MODE_NORMAL); if (ret) { dev_err(data->dev, "Failed to wake up the device\n"); - goto out; + goto err_reg_disable; } /* * TODO: The datasheet waits 1500us here in the example, but @@ -599,15 +622,15 @@ static int bma400_init(struct bma400_data *data) ret = bma400_get_accel_output_data_rate(data); if (ret) - goto out; + goto err_reg_disable; ret = bma400_get_accel_oversampling_ratio(data); if (ret) - goto out; + goto err_reg_disable; ret = bma400_get_accel_scale(data); if (ret) - goto out; + goto err_reg_disable; /* * Once the interrupt engine is supported we might use the @@ -617,6 +640,9 @@ static int bma400_init(struct bma400_data *data) */ return regmap_write(data->regmap, BMA400_ACC_CONFIG2_REG, 0x00); +err_reg_disable: + regulator_bulk_disable(ARRAY_SIZE(data->regulators), + data->regulators); out: return ret; } @@ -812,6 +838,9 @@ int bma400_remove(struct device *dev) ret = bma400_set_power_mode(data, POWER_MODE_SLEEP); mutex_unlock(&data->mutex); + regulator_bulk_disable(ARRAY_SIZE(data->regulators), + data->regulators); + iio_device_unregister(indio_dev); return ret; From 2df57429d8bee8d26c860d78039c9aaf2b9daffe Mon Sep 17 00:00:00 2001 From: Daniel Junho Date: Tue, 17 Dec 2019 08:11:55 -0300 Subject: [PATCH 160/353] iio: adc: ad7923: Remove the unused defines Removes the unused define AD7923_CHANNEL_x from the code. Signed-off-by: Daniel Junho Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7923.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c index 3212eb4c0f25..969c06b7d2b7 100644 --- a/drivers/iio/adc/ad7923.c +++ b/drivers/iio/adc/ad7923.c @@ -29,10 +29,6 @@ #define AD7923_PM_MODE_AS (1) /* auto shutdown */ #define AD7923_PM_MODE_FS (2) /* full shutdown */ #define AD7923_PM_MODE_OPS (3) /* normal operation */ -#define AD7923_CHANNEL_0 (0) /* analog input 0 */ -#define AD7923_CHANNEL_1 (1) /* analog input 1 */ -#define AD7923_CHANNEL_2 (2) /* analog input 2 */ -#define AD7923_CHANNEL_3 (3) /* analog input 3 */ #define AD7923_SEQUENCE_OFF (0) /* no sequence fonction */ #define AD7923_SEQUENCE_PROTECT (2) /* no interrupt write cycle */ #define AD7923_SEQUENCE_ON (3) /* continuous sequence */ From c87de1ba35e4e4225f3e10b09d22c6490e6cd848 Mon Sep 17 00:00:00 2001 From: Daniel Junho Date: Tue, 17 Dec 2019 08:11:56 -0300 Subject: [PATCH 161/353] iio: adc: ad7923: Fix checkpatch warning Fix checkpatch warning: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' +static int ad7923_scan_direct(struct ad7923_state *st, unsigned ch) Signed-off-by: Daniel Junho Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7923.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c index 969c06b7d2b7..e535cec9fc02 100644 --- a/drivers/iio/adc/ad7923.c +++ b/drivers/iio/adc/ad7923.c @@ -184,7 +184,7 @@ done: return IRQ_HANDLED; } -static int ad7923_scan_direct(struct ad7923_state *st, unsigned ch) +static int ad7923_scan_direct(struct ad7923_state *st, unsigned int ch) { int ret, cmd; From 233e7de42fcc3ba6abdc09a58a1be5577a09aba9 Mon Sep 17 00:00:00 2001 From: Daniel Junho Date: Tue, 17 Dec 2019 08:11:57 -0300 Subject: [PATCH 162/353] iio: adc: ad7923: Add of_device_id table Accomplish device tree compatibility to driver AD7923 by adding of_device_id table and making a subsequent call to MODULE_DEVICE_TABLE. Signed-off-by: Daniel Junho Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7923.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c index e535cec9fc02..6d56fa0b9e30 100644 --- a/drivers/iio/adc/ad7923.c +++ b/drivers/iio/adc/ad7923.c @@ -348,9 +348,19 @@ static const struct spi_device_id ad7923_id[] = { }; MODULE_DEVICE_TABLE(spi, ad7923_id); +static const struct of_device_id ad7923_of_match[] = { + { .compatible = "adi,ad7904", }, + { .compatible = "adi,ad7914", }, + { .compatible = "adi,ad7923", }, + { .compatible = "adi,ad7924", }, + { }, +}; +MODULE_DEVICE_TABLE(of, ad7923_of_match); + static struct spi_driver ad7923_driver = { .driver = { .name = "ad7923", + .of_match_table = ad7923_of_match, }, .probe = ad7923_probe, .remove = ad7923_remove, From 851644a60d200c9a294de5a5594004bcf13d34c7 Mon Sep 17 00:00:00 2001 From: Daniel Junho Date: Tue, 17 Dec 2019 08:11:58 -0300 Subject: [PATCH 163/353] iio: adc: ad7923: Add support for the ad7908/ad7918/ad7928 The ad7928 is software compatible with the ad7923. The ad7908 and ad7918 are the 8 and 10-bit versions of the ad7928. Signed-off-by: Daniel Junho Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7923.c | 48 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c index 6d56fa0b9e30..1d124c87c6ac 100644 --- a/drivers/iio/adc/ad7923.c +++ b/drivers/iio/adc/ad7923.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * AD7904/AD7914/AD7923/AD7924 SPI ADC driver + * AD7904/AD7914/AD7923/AD7924/AD7908/AD7918/AD7928 SPI ADC driver * * Copyright 2011 Analog Devices Inc (from AD7923 Driver) * Copyright 2012 CS Systemes d'Information @@ -33,7 +33,6 @@ #define AD7923_SEQUENCE_PROTECT (2) /* no interrupt write cycle */ #define AD7923_SEQUENCE_ON (3) /* continuous sequence */ -#define AD7923_MAX_CHAN 4 #define AD7923_PM_MODE_WRITE(mode) ((mode) << 4) /* write mode */ #define AD7923_CHANNEL_WRITE(channel) ((channel) << 6) /* write channel */ @@ -74,6 +73,9 @@ enum ad7923_id { AD7904, AD7914, AD7924, + AD7908, + AD7918, + AD7928 }; #define AD7923_V_CHAN(index, bits) \ @@ -102,9 +104,25 @@ const struct iio_chan_spec name ## _channels[] = { \ IIO_CHAN_SOFT_TIMESTAMP(4), \ } +#define DECLARE_AD7908_CHANNELS(name, bits) \ +const struct iio_chan_spec name ## _channels[] = { \ + AD7923_V_CHAN(0, bits), \ + AD7923_V_CHAN(1, bits), \ + AD7923_V_CHAN(2, bits), \ + AD7923_V_CHAN(3, bits), \ + AD7923_V_CHAN(4, bits), \ + AD7923_V_CHAN(5, bits), \ + AD7923_V_CHAN(6, bits), \ + AD7923_V_CHAN(7, bits), \ + IIO_CHAN_SOFT_TIMESTAMP(8), \ +} + static DECLARE_AD7923_CHANNELS(ad7904, 8); static DECLARE_AD7923_CHANNELS(ad7914, 10); static DECLARE_AD7923_CHANNELS(ad7924, 12); +static DECLARE_AD7908_CHANNELS(ad7908, 8); +static DECLARE_AD7908_CHANNELS(ad7918, 10); +static DECLARE_AD7908_CHANNELS(ad7928, 12); static const struct ad7923_chip_info ad7923_chip_info[] = { [AD7904] = { @@ -119,6 +137,18 @@ static const struct ad7923_chip_info ad7923_chip_info[] = { .channels = ad7924_channels, .num_channels = ARRAY_SIZE(ad7924_channels), }, + [AD7908] = { + .channels = ad7908_channels, + .num_channels = ARRAY_SIZE(ad7908_channels), + }, + [AD7918] = { + .channels = ad7918_channels, + .num_channels = ARRAY_SIZE(ad7918_channels), + }, + [AD7928] = { + .channels = ad7928_channels, + .num_channels = ARRAY_SIZE(ad7928_channels), + }, }; /** @@ -131,7 +161,11 @@ static int ad7923_update_scan_mode(struct iio_dev *indio_dev, int i, cmd, len; len = 0; - for_each_set_bit(i, active_scan_mask, AD7923_MAX_CHAN) { + /* + * For this driver the last channel is always the software timestamp so + * skip that one. + */ + for_each_set_bit(i, active_scan_mask, indio_dev->num_channels - 1) { cmd = AD7923_WRITE_CR | AD7923_CHANNEL_WRITE(i) | AD7923_SEQUENCE_WRITE(AD7923_SEQUENCE_OFF) | st->settings; @@ -344,6 +378,9 @@ static const struct spi_device_id ad7923_id[] = { {"ad7914", AD7914}, {"ad7923", AD7924}, {"ad7924", AD7924}, + {"ad7908", AD7908}, + {"ad7918", AD7918}, + {"ad7928", AD7928}, {} }; MODULE_DEVICE_TABLE(spi, ad7923_id); @@ -353,6 +390,9 @@ static const struct of_device_id ad7923_of_match[] = { { .compatible = "adi,ad7914", }, { .compatible = "adi,ad7923", }, { .compatible = "adi,ad7924", }, + { .compatible = "adi,ad7908", }, + { .compatible = "adi,ad7918", }, + { .compatible = "adi,ad7928", }, { }, }; MODULE_DEVICE_TABLE(of, ad7923_of_match); @@ -370,5 +410,5 @@ module_spi_driver(ad7923_driver); MODULE_AUTHOR("Michael Hennerich "); MODULE_AUTHOR("Patrick Vasseur "); -MODULE_DESCRIPTION("Analog Devices AD7904/AD7914/AD7923/AD7924 ADC"); +MODULE_DESCRIPTION("Analog Devices AD7923 and similar ADC"); MODULE_LICENSE("GPL v2"); From 07bf07e2cc7d8658de138b8a217cb0a936d26e7e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 20:19:23 +0200 Subject: [PATCH 164/353] iio: st_lsm6dsx: Mark predefined constants with __maybe_unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we put static variable to a header file it's copied to each module that includes the header. But not all of them are actually used it. Mark predefined constants with __maybe_unused to calm a compiler down: In file included from drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c:17: .../st_lsm6dsx/st_lsm6dsx.h:399:28: warning: ‘st_lsm6dsx_available_scan_masks’ defined but not used [-Wunused-const-variable=] 399 | static const unsigned long st_lsm6dsx_available_scan_masks[] = {0x7, 0x0}; | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .../st_lsm6dsx/st_lsm6dsx.h:392:36: warning: ‘st_lsm6dsx_event’ defined but not used [-Wunused-const-variable=] 392 | static const struct iio_event_spec st_lsm6dsx_event = { | ^~~~~~~~~~~~~~~~ ... Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index c605b153be41..f1189eef6e37 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -391,14 +391,17 @@ struct st_lsm6dsx_hw { const struct st_lsm6dsx_settings *settings; }; -static const struct iio_event_spec st_lsm6dsx_event = { +static __maybe_unused const struct iio_event_spec st_lsm6dsx_event = { .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_EITHER, .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE) }; -static const unsigned long st_lsm6dsx_available_scan_masks[] = {0x7, 0x0}; +static __maybe_unused const unsigned long st_lsm6dsx_available_scan_masks[] = { + 0x7, 0x0, +}; + extern const struct dev_pm_ops st_lsm6dsx_pm_ops; int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, From e3da43077046d3b44da0f66b2f202e25ba9ca694 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 20:19:24 +0200 Subject: [PATCH 165/353] iio: st_lsm6dsx: Drop unneeded OF code There is no need to have OF guard against ID table. Drop it for good. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c | 3 +-- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c index cd47ec1fedcb..0fb32131afce 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "st_lsm6dsx.h" @@ -122,7 +121,7 @@ static struct i2c_driver st_lsm6dsx_driver = { .driver = { .name = "st_lsm6dsx_i2c", .pm = &st_lsm6dsx_pm_ops, - .of_match_table = of_match_ptr(st_lsm6dsx_i2c_of_match), + .of_match_table = st_lsm6dsx_i2c_of_match, }, .probe = st_lsm6dsx_i2c_probe, .id_table = st_lsm6dsx_i2c_id_table, diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c index 67ff36eac247..eb1086e4a951 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "st_lsm6dsx.h" @@ -122,7 +121,7 @@ static struct spi_driver st_lsm6dsx_driver = { .driver = { .name = "st_lsm6dsx_spi", .pm = &st_lsm6dsx_pm_ops, - .of_match_table = of_match_ptr(st_lsm6dsx_spi_of_match), + .of_match_table = st_lsm6dsx_spi_of_match, }, .probe = st_lsm6dsx_spi_probe, .id_table = st_lsm6dsx_spi_id_table, From 03d4c566c51def8151dee1e87dae6479722890d2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 20:19:25 +0200 Subject: [PATCH 166/353] iio: st_lsm6dsx: Make use of device properties Device property API allows to gather device resources from different sources, such as ACPI. Convert the drivers to unleash the power of device property API. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 26 ++++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index a4ed72aef93e..95d7eb1d9cdb 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -1804,14 +1805,14 @@ static const struct iio_info st_lsm6dsx_gyro_info = { .hwfifo_set_watermark = st_lsm6dsx_set_watermark, }; -static int st_lsm6dsx_of_get_drdy_pin(struct st_lsm6dsx_hw *hw, int *drdy_pin) +static int st_lsm6dsx_get_drdy_pin(struct st_lsm6dsx_hw *hw, int *drdy_pin) { - struct device_node *np = hw->dev->of_node; + struct device *dev = hw->dev; - if (!np) + if (!dev_fwnode(dev)) return -EINVAL; - return of_property_read_u32(np, "st,drdy-int-pin", drdy_pin); + return device_property_read_u32(dev, "st,drdy-int-pin", drdy_pin); } static int @@ -1820,7 +1821,7 @@ st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, { int err = 0, drdy_pin; - if (st_lsm6dsx_of_get_drdy_pin(hw, &drdy_pin) < 0) { + if (st_lsm6dsx_get_drdy_pin(hw, &drdy_pin) < 0) { struct st_sensors_platform_data *pdata; struct device *dev = hw->dev; @@ -1849,15 +1850,15 @@ st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw) { const struct st_lsm6dsx_shub_settings *hub_settings; - struct device_node *np = hw->dev->of_node; struct st_sensors_platform_data *pdata; + struct device *dev = hw->dev; unsigned int data; int err = 0; hub_settings = &hw->settings->shub_settings; - pdata = (struct st_sensors_platform_data *)hw->dev->platform_data; - if ((np && of_property_read_bool(np, "st,pullups")) || + pdata = (struct st_sensors_platform_data *)dev->platform_data; + if ((dev_fwnode(dev) && device_property_read_bool(dev, "st,pullups")) || (pdata && pdata->pullups)) { err = st_lsm6dsx_set_page(hw, true); if (err < 0) @@ -2135,9 +2136,9 @@ static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw) { - struct device_node *np = hw->dev->of_node; struct st_sensors_platform_data *pdata; const struct st_lsm6dsx_reg *reg; + struct device *dev = hw->dev; unsigned long irq_type; bool irq_active_low; int err; @@ -2165,8 +2166,8 @@ static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw) if (err < 0) return err; - pdata = (struct st_sensors_platform_data *)hw->dev->platform_data; - if ((np && of_property_read_bool(np, "drive-open-drain")) || + pdata = (struct st_sensors_platform_data *)dev->platform_data; + if ((dev_fwnode(dev) && device_property_read_bool(dev, "drive-open-drain")) || (pdata && pdata->open_drain)) { reg = &hw->settings->irq_config.od; err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, @@ -2196,7 +2197,6 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, { struct st_sensors_platform_data *pdata = dev->platform_data; const struct st_lsm6dsx_shub_settings *hub_settings; - struct device_node *np = dev->of_node; struct st_lsm6dsx_hw *hw; const char *name = NULL; int i, err; @@ -2259,7 +2259,7 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, return err; } - if ((np && of_property_read_bool(np, "wakeup-source")) || + if ((dev_fwnode(dev) && device_property_read_bool(dev, "wakeup-source")) || (pdata && pdata->wakeup_source)) device_init_wakeup(dev, true); From d9fa3fd4bc48881684d9d1a1c709187a01fc9a21 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 19:38:45 +0200 Subject: [PATCH 167/353] iio: light: st_uvis25: Drop unneeded header inclusion There is no evidence that the driver supports or needs ACPI APIs. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/light/st_uvis25_i2c.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/light/st_uvis25_i2c.c b/drivers/iio/light/st_uvis25_i2c.c index dacbac6a6662..4889bbeb0c73 100644 --- a/drivers/iio/light/st_uvis25_i2c.c +++ b/drivers/iio/light/st_uvis25_i2c.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include From 4c3e7367bd7477f0335ab7f40505f9e03bf193a3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 19:38:46 +0200 Subject: [PATCH 168/353] iio: accel: st_accel: Drop unnecessary #else branch for ACPI ACPI_PTR() takes care of the argument in case of !CONFIG_ACPI. Remove unnecessary #else branch. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_i2c.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index 50fa0fc32baa..0f4aef5448e7 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -119,8 +119,6 @@ static const struct acpi_device_id st_accel_acpi_match[] = { { }, }; MODULE_DEVICE_TABLE(acpi, st_accel_acpi_match); -#else -#define st_accel_acpi_match NULL #endif static const struct i2c_device_id st_accel_id_table[] = { From 40ca77d57f0163d3bd2ae826613a69039be0d052 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 19:38:47 +0200 Subject: [PATCH 169/353] iio: pressure: st_press: Drop unnecessary #else branch for ACPI ACPI_PTR() takes care of the argument in case of !CONFIG_ACPI. Remove unnecessary #else branch. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/st_pressure_i2c.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index 71d2ed6b4948..6203bc9d5c2d 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -61,8 +61,6 @@ static const struct acpi_device_id st_press_acpi_match[] = { { }, }; MODULE_DEVICE_TABLE(acpi, st_press_acpi_match); -#else -#define st_press_acpi_match NULL #endif static const struct i2c_device_id st_press_id_table[] = { From f22b1d7588b1cc115d15462bb0f118be971369fb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 19:38:48 +0200 Subject: [PATCH 170/353] iio: gyro: st_gyro: Mark gyro_pdata with __maybe_unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we put static variable to a header file it's copied to each module that includes the header. But not all of them are actually used it. Mark gyro_pdata with __maybe_unused to calm a compiler down: In file included from drivers/iio/gyro/st_gyro_i2c.c:18: drivers/iio/gyro/st_gyro.h:31:46: warning: ‘gyro_pdata’ defined but not used [-Wunused-const-variable=] 31 | static const struct st_sensors_platform_data gyro_pdata = { | ^~~~~~~~~~ ... Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/st_gyro.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h index 592f6b34e987..fd9171cc3aba 100644 --- a/drivers/iio/gyro/st_gyro.h +++ b/drivers/iio/gyro/st_gyro.h @@ -28,7 +28,7 @@ * struct st_sensors_platform_data - gyro platform data * @drdy_int_pin: DRDY on gyros is available only on INT2 pin. */ -static const struct st_sensors_platform_data gyro_pdata = { +static __maybe_unused const struct st_sensors_platform_data gyro_pdata = { .drdy_int_pin = 2, }; From 2e8bd34a16f833c6e4d2fd725bac2cdb8faf61fc Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 19:38:49 +0200 Subject: [PATCH 171/353] iio: accel: st_accel: Mark default_accel_pdata with __maybe_unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we put static variable to a header file it's copied to each module that includes the header. But not all of them are actually used it. Mark default_accel_pdata with __maybe_unused to calm a compiler down: In file included from drivers/iio/accel/st_accel_i2c.c:19: drivers/iio/accel/st_accel.h:67:46: warning: ‘default_accel_pdata’ defined but not used [-Wunused-const-variable=] 67 | static const struct st_sensors_platform_data default_accel_pdata = { | ^~~~~~~~~~~~~~~~~~~ ... Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h index af09943f38c9..5b13e293cade 100644 --- a/drivers/iio/accel/st_accel.h +++ b/drivers/iio/accel/st_accel.h @@ -64,7 +64,7 @@ enum st_accel_type { * struct st_sensors_platform_data - default accel platform data * @drdy_int_pin: default accel DRDY is available on INT1 pin. */ -static const struct st_sensors_platform_data default_accel_pdata = { +static __maybe_unused const struct st_sensors_platform_data default_accel_pdata = { .drdy_int_pin = 1, }; From be4ac8321ff2c0085573500ce819e80cfa38d770 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 19:38:50 +0200 Subject: [PATCH 172/353] iio: pressure: st_press: Mark default_press_pdata with __maybe_unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we put static variable to a header file it's copied to each module that includes the header. But not all of them are actually used it. Mark default_press_pdata with __maybe_unused to calm a compiler down: In file included from drivers/iio/pressure/st_pressure_spi.c:18: drivers/iio/pressure/st_pressure.h:40:46: warning: ‘default_press_pdata’ defined but not used [-Wunused-const-variable=] 40 | static const struct st_sensors_platform_data default_press_pdata = { | ^~~~~~~~~~~~~~~~~~~ ... Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/st_pressure.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/pressure/st_pressure.h b/drivers/iio/pressure/st_pressure.h index c2e47a6c3118..5c746ff6087e 100644 --- a/drivers/iio/pressure/st_pressure.h +++ b/drivers/iio/pressure/st_pressure.h @@ -37,7 +37,7 @@ enum st_press_type { * struct st_sensors_platform_data - default press platform data * @drdy_int_pin: default press DRDY is available on INT1 pin. */ -static const struct st_sensors_platform_data default_press_pdata = { +static __maybe_unused const struct st_sensors_platform_data default_press_pdata = { .drdy_int_pin = 1, }; From de54fff151335d0c24f53ff843c67a1364f70f42 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 19:38:51 +0200 Subject: [PATCH 173/353] iio: st_sensors: Describe function parameters in kernel-doc Kernel documentation script complains that some of the function parameters are not described: .../common/st_sensors/st_sensors_trigger.c:29: warning: Function parameter or member 'indio_dev' not described in 'st_sensors_new_samples_available' .../common/st_sensors/st_sensors_trigger.c:29: warning: Function parameter or member 'sdata' not described in 'st_sensors_new_samples_available' Describe function parameters where it's appropriate. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/common/st_sensors/st_sensors_trigger.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c index 4a2efa00f7f2..e817537cdfb5 100644 --- a/drivers/iio/common/st_sensors/st_sensors_trigger.c +++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c @@ -19,6 +19,9 @@ /** * st_sensors_new_samples_available() - check if more samples came in + * @indio_dev: IIO device reference. + * @sdata: Sensor data. + * * returns: * 0 - no new samples available * 1 - new samples available From 0d15190f53b4e21aa3d15f1ace4c0807a269a763 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Sun, 15 Dec 2019 16:00:45 -0800 Subject: [PATCH 174/353] iio: chemical: atlas-ph-sensor: rename atlas-ph-sensor to atlas-sensor Since the orginal scope of the driver was to only support the pH product from Atlas it has evolved to other sensors. Rename the file, driver name, and regmap to atlas-sensor which reflects this, although keep CONFIG_ATLAS_PH_SENSOR to not cause regressions with current configurations. Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/chemical/Makefile | 2 +- .../iio/chemical/{atlas-ph-sensor.c => atlas-sensor.c} | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) rename drivers/iio/chemical/{atlas-ph-sensor.c => atlas-sensor.c} (98%) diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile index f97270bc4034..33d3a595dda9 100644 --- a/drivers/iio/chemical/Makefile +++ b/drivers/iio/chemical/Makefile @@ -4,7 +4,7 @@ # # When adding new entries keep the list in alphabetical order -obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-ph-sensor.o +obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-sensor.o obj-$(CONFIG_BME680) += bme680_core.o obj-$(CONFIG_BME680_I2C) += bme680_i2c.o obj-$(CONFIG_BME680_SPI) += bme680_spi.o diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-sensor.c similarity index 98% rename from drivers/iio/chemical/atlas-ph-sensor.c rename to drivers/iio/chemical/atlas-sensor.c index b7c20c74239b..99095c80531b 100644 --- a/drivers/iio/chemical/atlas-ph-sensor.c +++ b/drivers/iio/chemical/atlas-sensor.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * atlas-ph-sensor.c - Support for Atlas Scientific OEM pH-SM sensor + * atlas-sensor.c - Support for Atlas Scientific OEM SM sensors * - * Copyright (C) 2015-2018 Matt Ranostay + * Copyright (C) 2015-2019 Konsulko Group * Author: Matt Ranostay */ @@ -24,8 +24,8 @@ #include #include -#define ATLAS_REGMAP_NAME "atlas_ph_regmap" -#define ATLAS_DRV_NAME "atlas_ph" +#define ATLAS_REGMAP_NAME "atlas_regmap" +#define ATLAS_DRV_NAME "atlas" #define ATLAS_REG_DEV_TYPE 0x00 #define ATLAS_REG_DEV_VERSION 0x01 @@ -680,5 +680,5 @@ static struct i2c_driver atlas_driver = { module_i2c_driver(atlas_driver); MODULE_AUTHOR("Matt Ranostay "); -MODULE_DESCRIPTION("Atlas Scientific pH-SM sensor"); +MODULE_DESCRIPTION("Atlas Scientific SM sensors"); MODULE_LICENSE("GPL"); From 4dae3d6147b362b1c4a35d3ef3177358d084d464 Mon Sep 17 00:00:00 2001 From: Chen Zhou Date: Mon, 16 Dec 2019 18:51:01 +0800 Subject: [PATCH 175/353] iio: light: remove unneeded semicolon Fixes coccicheck warning: ./drivers/iio/light/lm3533-als.c:745:2-3: Unneeded semicolon Signed-off-by: Chen Zhou Signed-off-by: Jonathan Cameron --- drivers/iio/light/lm3533-als.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c index 6733b52c22df..bc196c212881 100644 --- a/drivers/iio/light/lm3533-als.c +++ b/drivers/iio/light/lm3533-als.c @@ -742,7 +742,7 @@ static int lm3533_als_set_resistor(struct lm3533_als *als, u8 val) if (val < LM3533_ALS_RESISTOR_MIN || val > LM3533_ALS_RESISTOR_MAX) { dev_err(&als->pdev->dev, "invalid resistor value\n"); return -EINVAL; - }; + } ret = lm3533_write(als->lm3533, LM3533_REG_ALS_RESISTOR_SELECT, val); if (ret) { From ee978bb86d055131364baa617fbdb0a9bb52612a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 14 Dec 2019 17:52:54 +0100 Subject: [PATCH 176/353] iio: imu: st_lsm6dsx: export max num of slave devices in st_lsm6dsx_shub_settings Export max number of slave devices supported by the i2c master controller in st_lsm6dsx_shub_settings data structure. This is a preliminary patch to support i2c master controller on lsm6dsm sensors Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 2 ++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 2 ++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c | 3 +-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index f1189eef6e37..140e4c6971f3 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -176,6 +176,7 @@ struct st_lsm6dsx_hw_ts_settings { * @pullup_en: i2c controller pull-up register info (addr + mask). * @aux_sens: aux sensor register info (addr + mask). * @wr_once: write_once register info (addr + mask). + * @num_ext_dev: max number of slave devices. * @shub_out: sensor hub first output register info. * @slv0_addr: slave0 address in secondary page. * @dw_slv0_addr: slave0 write register address in secondary page. @@ -187,6 +188,7 @@ struct st_lsm6dsx_shub_settings { struct st_lsm6dsx_reg pullup_en; struct st_lsm6dsx_reg aux_sens; struct st_lsm6dsx_reg wr_once; + u8 num_ext_dev; u8 shub_out; u8 slv0_addr; u8 dw_slv0_addr; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 95d7eb1d9cdb..91dc9796add7 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -883,6 +883,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x14, .mask = BIT(6), }, + .num_ext_dev = 3, .shub_out = 0x02, .slv0_addr = 0x15, .dw_slv0_addr = 0x21, @@ -1257,6 +1258,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x14, .mask = BIT(6), }, + .num_ext_dev = 3, .shub_out = 0x02, .slv0_addr = 0x15, .dw_slv0_addr = 0x21, diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c index fa5d1001a46c..5684e663d0aa 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c @@ -30,7 +30,6 @@ #include "st_lsm6dsx.h" -#define ST_LSM6DSX_MAX_SLV_NUM 3 #define ST_LSM6DSX_SLV_ADDR(n, base) ((base) + (n) * 3) #define ST_LSM6DSX_SLV_SUB_ADDR(n, base) ((base) + 1 + (n) * 3) #define ST_LSM6DSX_SLV_CONFIG(n, base) ((base) + 2 + (n) * 3) @@ -770,7 +769,7 @@ int st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name) if (err < 0) return err; - if (++num_ext_dev >= ST_LSM6DSX_MAX_SLV_NUM) + if (++num_ext_dev >= hw->settings->shub_settings.num_ext_dev) break; id++; } From 007f2ebbac2ac7f0f6d80ca5afd3f51c5a083838 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 14 Dec 2019 17:52:55 +0100 Subject: [PATCH 177/353] iio: imu: st_lsm6dsx: check if master_enable is located in primary page Check if the master enable register is located in the primary or in the secondary memory page. This is a preliminary patch to support i2c master controller on lsm6dsm devices Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 6 +++++- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 2 ++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c | 11 +++++++---- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 140e4c6971f3..bd1c77d16147 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -184,7 +184,11 @@ struct st_lsm6dsx_hw_ts_settings { */ struct st_lsm6dsx_shub_settings { struct st_lsm6dsx_reg page_mux; - struct st_lsm6dsx_reg master_en; + struct { + bool sec_page; + u8 addr; + u8 mask; + } master_en; struct st_lsm6dsx_reg pullup_en; struct st_lsm6dsx_reg aux_sens; struct st_lsm6dsx_reg wr_once; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 91dc9796add7..b8cfea977968 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -868,6 +868,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .mask = BIT(6), }, .master_en = { + .sec_page = true, .addr = 0x14, .mask = BIT(2), }, @@ -1243,6 +1244,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .mask = BIT(6), }, .master_en = { + .sec_page = true, .addr = 0x14, .mask = BIT(2), }, diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c index 5684e663d0aa..767482e61a1e 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c @@ -185,15 +185,18 @@ static int st_lsm6dsx_shub_master_enable(struct st_lsm6dsx_sensor *sensor, mutex_lock(&hw->page_lock); hub_settings = &hw->settings->shub_settings; - err = st_lsm6dsx_set_page(hw, true); - if (err < 0) - goto out; + if (hub_settings->master_en.sec_page) { + err = st_lsm6dsx_set_page(hw, true); + if (err < 0) + goto out; + } data = ST_LSM6DSX_SHIFT_VAL(enable, hub_settings->master_en.mask); err = regmap_update_bits(hw->regmap, hub_settings->master_en.addr, hub_settings->master_en.mask, data); - st_lsm6dsx_set_page(hw, false); + if (hub_settings->master_en.sec_page) + st_lsm6dsx_set_page(hw, false); out: mutex_unlock(&hw->page_lock); From 3a4319574584ef5a71e11780cc83337282818882 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 14 Dec 2019 17:52:56 +0100 Subject: [PATCH 178/353] iio: imu: st_lsm6dsx: check if pull_up is located in primary page Check if the pull up register is located in the primary or in the secondary memory page. This is a preliminary patch to support i2c master controller on lsm6dsm devices Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 6 +++++- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 13 +++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index bd1c77d16147..4974f6fafd53 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -189,7 +189,11 @@ struct st_lsm6dsx_shub_settings { u8 addr; u8 mask; } master_en; - struct st_lsm6dsx_reg pullup_en; + struct { + bool sec_page; + u8 addr; + u8 mask; + } pullup_en; struct st_lsm6dsx_reg aux_sens; struct st_lsm6dsx_reg wr_once; u8 num_ext_dev; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index b8cfea977968..b5e9f71be085 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -873,6 +873,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .mask = BIT(2), }, .pullup_en = { + .sec_page = true, .addr = 0x14, .mask = BIT(3), }, @@ -1249,6 +1250,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .mask = BIT(2), }, .pullup_en = { + .sec_page = true, .addr = 0x14, .mask = BIT(3), }, @@ -1864,16 +1866,19 @@ static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw) pdata = (struct st_sensors_platform_data *)dev->platform_data; if ((dev_fwnode(dev) && device_property_read_bool(dev, "st,pullups")) || (pdata && pdata->pullups)) { - err = st_lsm6dsx_set_page(hw, true); - if (err < 0) - return err; + if (hub_settings->pullup_en.sec_page) { + err = st_lsm6dsx_set_page(hw, true); + if (err < 0) + return err; + } data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->pullup_en.mask); err = regmap_update_bits(hw->regmap, hub_settings->pullup_en.addr, hub_settings->pullup_en.mask, data); - st_lsm6dsx_set_page(hw, false); + if (hub_settings->pullup_en.sec_page) + st_lsm6dsx_set_page(hw, false); if (err < 0) return err; From 5b8343e067f8c0ce6e480659956d011e876d3635 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 14 Dec 2019 17:52:57 +0100 Subject: [PATCH 179/353] iio: imu: st_lsm6dsx: check if shub_output reg is located in primary page Check if the sensor hub output register is located in the primary or in the secondary memory page. This is a preliminary patch to support i2c master controller on lsm6dsm devices Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 5 +++- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 10 +++++-- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c | 28 +++++++++++--------- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 4974f6fafd53..001179e19ba7 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -197,7 +197,10 @@ struct st_lsm6dsx_shub_settings { struct st_lsm6dsx_reg aux_sens; struct st_lsm6dsx_reg wr_once; u8 num_ext_dev; - u8 shub_out; + struct { + bool sec_page; + u8 addr; + } shub_out; u8 slv0_addr; u8 dw_slv0_addr; u8 batch_en; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index b5e9f71be085..49ad70c589bd 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -886,7 +886,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .mask = BIT(6), }, .num_ext_dev = 3, - .shub_out = 0x02, + .shub_out = { + .sec_page = true, + .addr = 0x02, + }, .slv0_addr = 0x15, .dw_slv0_addr = 0x21, .batch_en = BIT(3), @@ -1263,7 +1266,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .mask = BIT(6), }, .num_ext_dev = 3, - .shub_out = 0x02, + .shub_out = { + .sec_page = true, + .addr = 0x02, + }, .slv0_addr = 0x15, .dw_slv0_addr = 0x21, .batch_en = BIT(3), diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c index 767482e61a1e..ccc59682cb66 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c @@ -105,20 +105,27 @@ static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw) * * Read st_lsm6dsx i2c controller register */ -static int st_lsm6dsx_shub_read_reg(struct st_lsm6dsx_hw *hw, u8 addr, - u8 *data, int len) +static int +st_lsm6dsx_shub_read_reg(struct st_lsm6dsx_hw *hw, u8 *data, + int len) { + const struct st_lsm6dsx_shub_settings *hub_settings; int err; mutex_lock(&hw->page_lock); - err = st_lsm6dsx_set_page(hw, true); - if (err < 0) - goto out; + hub_settings = &hw->settings->shub_settings; + if (hub_settings->shub_out.sec_page) { + err = st_lsm6dsx_set_page(hw, true); + if (err < 0) + goto out; + } - err = regmap_bulk_read(hw->regmap, addr, data, len); + err = regmap_bulk_read(hw->regmap, hub_settings->shub_out.addr, + data, len); - st_lsm6dsx_set_page(hw, false); + if (hub_settings->shub_out.sec_page) + st_lsm6dsx_set_page(hw, false); out: mutex_unlock(&hw->page_lock); @@ -236,8 +243,7 @@ st_lsm6dsx_shub_read(struct st_lsm6dsx_sensor *sensor, u8 addr, st_lsm6dsx_shub_wait_complete(hw); - err = st_lsm6dsx_shub_read_reg(hw, hub_settings->shub_out, data, - len & ST_LS6DSX_READ_OP_MASK); + err = st_lsm6dsx_shub_read_reg(hw, data, len & ST_LS6DSX_READ_OP_MASK); st_lsm6dsx_shub_master_enable(sensor, false); @@ -719,9 +725,7 @@ st_lsm6dsx_shub_check_wai(struct st_lsm6dsx_hw *hw, u8 *i2c_addr, st_lsm6dsx_shub_wait_complete(hw); - err = st_lsm6dsx_shub_read_reg(hw, - hub_settings->shub_out, - &data, sizeof(data)); + err = st_lsm6dsx_shub_read_reg(hw, &data, sizeof(data)); st_lsm6dsx_shub_master_enable(sensor, false); From 111b0875774b9622161e2ed6dd176e21c8665da0 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 14 Dec 2019 17:52:58 +0100 Subject: [PATCH 180/353] iio: imu: st_lsm6dsx: rename st_lsm6dsx_shub_read_reg in st_lsm6dsx_shub_read_output Rename st_lsm6dsx_shub_read_reg routine in st_lsm6dsx_shub_read_output since it is used to read from sensorhub channel0 output register Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c index ccc59682cb66..dc739dfb36f2 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c @@ -101,13 +101,13 @@ static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw) } /** - * st_lsm6dsx_shub_read_reg - read i2c controller register + * st_lsm6dsx_shub_read_output - read i2c controller register * * Read st_lsm6dsx i2c controller register */ static int -st_lsm6dsx_shub_read_reg(struct st_lsm6dsx_hw *hw, u8 *data, - int len) +st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data, + int len) { const struct st_lsm6dsx_shub_settings *hub_settings; int err; @@ -243,7 +243,8 @@ st_lsm6dsx_shub_read(struct st_lsm6dsx_sensor *sensor, u8 addr, st_lsm6dsx_shub_wait_complete(hw); - err = st_lsm6dsx_shub_read_reg(hw, data, len & ST_LS6DSX_READ_OP_MASK); + err = st_lsm6dsx_shub_read_output(hw, data, + len & ST_LS6DSX_READ_OP_MASK); st_lsm6dsx_shub_master_enable(sensor, false); @@ -725,7 +726,7 @@ st_lsm6dsx_shub_check_wai(struct st_lsm6dsx_hw *hw, u8 *i2c_addr, st_lsm6dsx_shub_wait_complete(hw); - err = st_lsm6dsx_shub_read_reg(hw, &data, sizeof(data)); + err = st_lsm6dsx_shub_read_output(hw, &data, sizeof(data)); st_lsm6dsx_shub_master_enable(sensor, false); From e485e2a2cfd6404d21066be6378ed42f8ce81060 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 14 Dec 2019 17:52:59 +0100 Subject: [PATCH 181/353] iio: imu: st_lsm6dsx: enable sensor-hub support for lsm6dsm Enabled i2c master controller support for LSM6DSM sensor. Enable ext_sensor0 for lsm6dsm. This series has been tested using LIS2MDL as slave device connected to the i2c controller of the LSM6DSM Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 4 ++ .../iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 27 ++++++++--- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 47 +++++++++++++++++++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c | 33 +++++++++---- 4 files changed, 95 insertions(+), 16 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 001179e19ba7..a763ff46f596 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -176,11 +176,13 @@ struct st_lsm6dsx_hw_ts_settings { * @pullup_en: i2c controller pull-up register info (addr + mask). * @aux_sens: aux sensor register info (addr + mask). * @wr_once: write_once register info (addr + mask). + * @emb_func: embedded function register info (addr + mask). * @num_ext_dev: max number of slave devices. * @shub_out: sensor hub first output register info. * @slv0_addr: slave0 address in secondary page. * @dw_slv0_addr: slave0 write register address in secondary page. * @batch_en: Enable/disable FIFO batching. + * @pause: controller pause value. */ struct st_lsm6dsx_shub_settings { struct st_lsm6dsx_reg page_mux; @@ -196,6 +198,7 @@ struct st_lsm6dsx_shub_settings { } pullup_en; struct st_lsm6dsx_reg aux_sens; struct st_lsm6dsx_reg wr_once; + struct st_lsm6dsx_reg emb_func; u8 num_ext_dev; struct { bool sec_page; @@ -204,6 +207,7 @@ struct st_lsm6dsx_shub_settings { u8 slv0_addr; u8 dw_slv0_addr; u8 batch_en; + u8 pause; }; struct st_lsm6dsx_event_settings { diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index d416990ae309..cc2b19b60d61 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -332,12 +332,13 @@ static inline int st_lsm6dsx_read_block(struct st_lsm6dsx_hw *hw, u8 addr, */ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) { + struct st_lsm6dsx_sensor *acc_sensor, *gyro_sensor, *ext_sensor = NULL; + int err, acc_sip, gyro_sip, ts_sip, ext_sip, read_len, offset; u16 fifo_len, pattern_len = hw->sip * ST_LSM6DSX_SAMPLE_SIZE; u16 fifo_diff_mask = hw->settings->fifo_ops.fifo_diff.mask; - int err, acc_sip, gyro_sip, ts_sip, read_len, offset; - struct st_lsm6dsx_sensor *acc_sensor, *gyro_sensor; u8 gyro_buff[ST_LSM6DSX_IIO_BUFF_SIZE]; u8 acc_buff[ST_LSM6DSX_IIO_BUFF_SIZE]; + u8 ext_buff[ST_LSM6DSX_IIO_BUFF_SIZE]; bool reset_ts = false; __le16 fifo_status; s64 ts = 0; @@ -360,6 +361,8 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) acc_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); gyro_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_GYRO]); + if (hw->iio_devs[ST_LSM6DSX_ID_EXT0]) + ext_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_EXT0]); for (read_len = 0; read_len < fifo_len; read_len += pattern_len) { err = st_lsm6dsx_read_block(hw, ST_LSM6DSX_REG_FIFO_OUTL_ADDR, @@ -387,12 +390,13 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) * following pattern is repeated every 9 samples: * - Gx, Gy, Gz, Ax, Ay, Az, Ts, Gx, Gy, Gz, Ts, Gx, .. */ + ext_sip = ext_sensor ? ext_sensor->sip : 0; gyro_sip = gyro_sensor->sip; acc_sip = acc_sensor->sip; ts_sip = hw->ts_sip; offset = 0; - while (acc_sip > 0 || gyro_sip > 0) { + while (acc_sip > 0 || gyro_sip > 0 || ext_sip > 0) { if (gyro_sip > 0) { memcpy(gyro_buff, &hw->buff[offset], ST_LSM6DSX_SAMPLE_SIZE); @@ -403,6 +407,11 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) ST_LSM6DSX_SAMPLE_SIZE); offset += ST_LSM6DSX_SAMPLE_SIZE; } + if (ext_sip > 0) { + memcpy(ext_buff, &hw->buff[offset], + ST_LSM6DSX_SAMPLE_SIZE); + offset += ST_LSM6DSX_SAMPLE_SIZE; + } if (ts_sip-- > 0) { u8 data[ST_LSM6DSX_SAMPLE_SIZE]; @@ -436,6 +445,10 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) iio_push_to_buffers_with_timestamp( hw->iio_devs[ST_LSM6DSX_ID_ACC], acc_buff, acc_sensor->ts_ref + ts); + if (ext_sip-- > 0) + iio_push_to_buffers_with_timestamp( + hw->iio_devs[ST_LSM6DSX_ID_EXT0], + ext_buff, ext_sensor->ts_ref + ts); } } @@ -628,12 +641,12 @@ int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable) err = st_lsm6dsx_sensor_set_enable(sensor, enable); if (err < 0) goto out; - - err = st_lsm6dsx_set_fifo_odr(sensor, enable); - if (err < 0) - goto out; } + err = st_lsm6dsx_set_fifo_odr(sensor, enable); + if (err < 0) + goto out; + err = st_lsm6dsx_update_decimators(hw); if (err < 0) goto out; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 49ad70c589bd..0c64e35c7599 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -656,6 +656,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x08, .mask = GENMASK(5, 3), }, + [ST_LSM6DSX_ID_EXT0] = { + .addr = 0x09, + .mask = GENMASK(2, 0), + }, }, .fifo_ops = { .update_fifo = st_lsm6dsx_update_fifo, @@ -688,6 +692,39 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .mask = GENMASK(5, 3), }, }, + .shub_settings = { + .page_mux = { + .addr = 0x01, + .mask = BIT(7), + }, + .master_en = { + .addr = 0x1a, + .mask = BIT(0), + }, + .pullup_en = { + .addr = 0x1a, + .mask = BIT(3), + }, + .aux_sens = { + .addr = 0x04, + .mask = GENMASK(5, 4), + }, + .wr_once = { + .addr = 0x07, + .mask = BIT(5), + }, + .emb_func = { + .addr = 0x19, + .mask = BIT(2), + }, + .num_ext_dev = 1, + .shub_out = { + .addr = 0x2e, + }, + .slv0_addr = 0x02, + .dw_slv0_addr = 0x0e, + .pause = 0x7, + }, .event_settings = { .enable_reg = { .addr = 0x58, @@ -1902,6 +1939,16 @@ static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw) hub_settings->aux_sens.mask, data); st_lsm6dsx_set_page(hw, false); + + if (err < 0) + return err; + } + + if (hub_settings->emb_func.addr) { + data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->emb_func.mask); + err = regmap_update_bits(hw->regmap, + hub_settings->emb_func.addr, + hub_settings->emb_func.mask, data); } return err; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c index dc739dfb36f2..eea555617d4a 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c @@ -221,16 +221,21 @@ st_lsm6dsx_shub_read(struct st_lsm6dsx_sensor *sensor, u8 addr, u8 *data, int len) { const struct st_lsm6dsx_shub_settings *hub_settings; + u8 config[3], slv_addr, slv_config = 0; struct st_lsm6dsx_hw *hw = sensor->hw; - u8 config[3], slv_addr; + const struct st_lsm6dsx_reg *aux_sens; int err; hub_settings = &hw->settings->shub_settings; slv_addr = ST_LSM6DSX_SLV_ADDR(0, hub_settings->slv0_addr); + aux_sens = &hw->settings->shub_settings.aux_sens; + /* do not overwrite aux_sens */ + if (slv_addr + 2 == aux_sens->addr) + slv_config = ST_LSM6DSX_SHIFT_VAL(3, aux_sens->mask); config[0] = (sensor->ext_info.addr << 1) | 1; config[1] = addr; - config[2] = len & ST_LS6DSX_READ_OP_MASK; + config[2] = (len & ST_LS6DSX_READ_OP_MASK) | slv_config; err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config, sizeof(config)); @@ -248,7 +253,9 @@ st_lsm6dsx_shub_read(struct st_lsm6dsx_sensor *sensor, u8 addr, st_lsm6dsx_shub_master_enable(sensor, false); - memset(config, 0, sizeof(config)); + config[0] = hub_settings->pause; + config[1] = 0; + config[2] = slv_config; return st_lsm6dsx_shub_write_reg(hw, slv_addr, config, sizeof(config)); } @@ -305,7 +312,8 @@ st_lsm6dsx_shub_write(struct st_lsm6dsx_sensor *sensor, u8 addr, st_lsm6dsx_shub_master_enable(sensor, false); } - memset(config, 0, sizeof(config)); + config[0] = hub_settings->pause; + config[1] = 0; return st_lsm6dsx_shub_write_reg(hw, slv_addr, config, sizeof(config)); } @@ -697,14 +705,19 @@ st_lsm6dsx_shub_check_wai(struct st_lsm6dsx_hw *hw, u8 *i2c_addr, const struct st_lsm6dsx_ext_dev_settings *settings) { const struct st_lsm6dsx_shub_settings *hub_settings; + u8 config[3], data, slv_addr, slv_config = 0; + const struct st_lsm6dsx_reg *aux_sens; struct st_lsm6dsx_sensor *sensor; - u8 config[3], data, slv_addr; bool found = false; int i, err; - hub_settings = &hw->settings->shub_settings; - slv_addr = ST_LSM6DSX_SLV_ADDR(0, hub_settings->slv0_addr); sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); + hub_settings = &hw->settings->shub_settings; + aux_sens = &hw->settings->shub_settings.aux_sens; + slv_addr = ST_LSM6DSX_SLV_ADDR(0, hub_settings->slv0_addr); + /* do not overwrite aux_sens */ + if (slv_addr + 2 == aux_sens->addr) + slv_config = ST_LSM6DSX_SHIFT_VAL(3, aux_sens->mask); for (i = 0; i < ARRAY_SIZE(settings->i2c_addr); i++) { if (!settings->i2c_addr[i]) @@ -713,7 +726,7 @@ st_lsm6dsx_shub_check_wai(struct st_lsm6dsx_hw *hw, u8 *i2c_addr, /* read wai slave register */ config[0] = (settings->i2c_addr[i] << 1) | 0x1; config[1] = settings->wai.addr; - config[2] = 0x1; + config[2] = 0x1 | slv_config; err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config, sizeof(config)); @@ -742,7 +755,9 @@ st_lsm6dsx_shub_check_wai(struct st_lsm6dsx_hw *hw, u8 *i2c_addr, } /* reset SLV0 channel */ - memset(config, 0, sizeof(config)); + config[0] = hub_settings->pause; + config[1] = 0; + config[2] = slv_config; err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config, sizeof(config)); if (err < 0) From 964172561ea65f92394ef823405c31f17c57cc90 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 11 Dec 2019 22:38:16 +0100 Subject: [PATCH 182/353] iio: accel: bma180: Add dev helper variable Having a shorthand "dev" instead of &client->dev everywhere makes the code easier to read (more compact). Cc: Peter Meerwald Cc: Oleksandr Kravchenko Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma180.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 1574e4604a4f..518efbe4eaf6 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -712,12 +712,13 @@ static const struct iio_trigger_ops bma180_trigger_ops = { static int bma180_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct bma180_data *data; struct iio_dev *indio_dev; enum chip_ids chip; int ret; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; @@ -725,12 +726,12 @@ static int bma180_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); data->client = client; if (client->dev.of_node) - chip = (enum chip_ids)of_device_get_match_data(&client->dev); + chip = (enum chip_ids)of_device_get_match_data(dev); else chip = id->driver_data; data->part_info = &bma180_part_info[chip]; - ret = iio_read_mount_matrix(&client->dev, "mount-matrix", + ret = iio_read_mount_matrix(dev, "mount-matrix", &data->orientation); if (ret) return ret; @@ -740,7 +741,7 @@ static int bma180_probe(struct i2c_client *client, goto err_chip_disable; mutex_init(&data->mutex); - indio_dev->dev.parent = &client->dev; + indio_dev->dev.parent = dev; indio_dev->channels = data->part_info->channels; indio_dev->num_channels = data->part_info->num_channels; indio_dev->name = id->name; @@ -755,15 +756,15 @@ static int bma180_probe(struct i2c_client *client, goto err_chip_disable; } - ret = devm_request_irq(&client->dev, client->irq, + ret = devm_request_irq(dev, client->irq, iio_trigger_generic_data_rdy_poll, IRQF_TRIGGER_RISING, "bma180_event", data->trig); if (ret) { - dev_err(&client->dev, "unable to request IRQ\n"); + dev_err(dev, "unable to request IRQ\n"); goto err_trigger_free; } - data->trig->dev.parent = &client->dev; + data->trig->dev.parent = dev; data->trig->ops = &bma180_trigger_ops; iio_trigger_set_drvdata(data->trig, indio_dev); indio_dev->trig = iio_trigger_get(data->trig); @@ -776,13 +777,13 @@ static int bma180_probe(struct i2c_client *client, ret = iio_triggered_buffer_setup(indio_dev, NULL, bma180_trigger_handler, NULL); if (ret < 0) { - dev_err(&client->dev, "unable to setup iio triggered buffer\n"); + dev_err(dev, "unable to setup iio triggered buffer\n"); goto err_trigger_unregister; } ret = iio_device_register(indio_dev); if (ret < 0) { - dev_err(&client->dev, "unable to register iio device\n"); + dev_err(dev, "unable to register iio device\n"); goto err_buffer_cleanup; } From c35aae7443023c08d406c9077c9e842b48cdb22f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 11 Dec 2019 22:38:17 +0100 Subject: [PATCH 183/353] iio: accel: bma180: Basic regulator support This brings up the VDD and VDDIO regulators using the regulator framework. Platforms that do not use regulators will provide stubs or dummy regulators. Cc: Peter Meerwald Cc: Oleksandr Kravchenko Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma180.c | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 518efbe4eaf6..c2c15a4f9ee1 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,8 @@ struct bma180_part_info { #define BMA250_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ struct bma180_data { + struct regulator *vdd_supply; + struct regulator *vddio_supply; struct i2c_client *client; struct iio_trigger *trig; const struct bma180_part_info *part_info; @@ -736,6 +739,40 @@ static int bma180_probe(struct i2c_client *client, if (ret) return ret; + data->vdd_supply = devm_regulator_get(dev, "vdd"); + if (IS_ERR(data->vdd_supply)) { + if (PTR_ERR(data->vdd_supply) != -EPROBE_DEFER) + dev_err(dev, "Failed to get vdd regulator %d\n", + (int)PTR_ERR(data->vdd_supply)); + return PTR_ERR(data->vdd_supply); + } + data->vddio_supply = devm_regulator_get(dev, "vddio"); + if (IS_ERR(data->vddio_supply)) { + if (PTR_ERR(data->vddio_supply) != -EPROBE_DEFER) + dev_err(dev, "Failed to get vddio regulator %d\n", + (int)PTR_ERR(data->vddio_supply)); + return PTR_ERR(data->vddio_supply); + } + /* Typical voltage 2.4V these are min and max */ + ret = regulator_set_voltage(data->vdd_supply, 1620000, 3600000); + if (ret) + return ret; + ret = regulator_set_voltage(data->vddio_supply, 1200000, 3600000); + if (ret) + return ret; + ret = regulator_enable(data->vdd_supply); + if (ret) { + dev_err(dev, "Failed to enable vdd regulator: %d\n", ret); + return ret; + } + ret = regulator_enable(data->vddio_supply); + if (ret) { + dev_err(dev, "Failed to enable vddio regulator: %d\n", ret); + goto err_disable_vdd; + } + /* Wait to make sure we started up properly (3 ms at least) */ + usleep_range(3000, 5000); + ret = data->part_info->chip_config(data); if (ret < 0) goto err_chip_disable; @@ -798,6 +835,9 @@ err_trigger_free: iio_trigger_free(data->trig); err_chip_disable: data->part_info->chip_disable(data); + regulator_disable(data->vddio_supply); +err_disable_vdd: + regulator_disable(data->vdd_supply); return ret; } @@ -817,6 +857,8 @@ static int bma180_remove(struct i2c_client *client) mutex_lock(&data->mutex); data->part_info->chip_disable(data); mutex_unlock(&data->mutex); + regulator_disable(data->vddio_supply); + regulator_disable(data->vdd_supply); return 0; } From 9436abc40139503a7cea22a96437697d048f31c0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 11 Dec 2019 22:38:18 +0100 Subject: [PATCH 184/353] iio: accel: bma180: Use explicit member assignment This uses the C99 explicit .member assignment for the variant data in struct bma180_part_info. This makes it easier to understand and add new variants. Cc: Peter Meerwald Cc: Oleksandr Kravchenko Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma180.c | 68 ++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index c2c15a4f9ee1..45dd096c0220 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -632,32 +632,52 @@ static const struct iio_chan_spec bma250_channels[] = { static const struct bma180_part_info bma180_part_info[] = { [BMA180] = { - bma180_channels, ARRAY_SIZE(bma180_channels), - bma180_scale_table, ARRAY_SIZE(bma180_scale_table), - bma180_bw_table, ARRAY_SIZE(bma180_bw_table), - BMA180_CTRL_REG0, BMA180_RESET_INT, - BMA180_CTRL_REG0, BMA180_SLEEP, - BMA180_BW_TCS, BMA180_BW, - BMA180_OFFSET_LSB1, BMA180_RANGE, - BMA180_TCO_Z, BMA180_MODE_CONFIG, BMA180_LOW_POWER, - BMA180_CTRL_REG3, BMA180_NEW_DATA_INT, - BMA180_RESET, - bma180_chip_config, - bma180_chip_disable, + .channels = bma180_channels, + .num_channels = ARRAY_SIZE(bma180_channels), + .scale_table = bma180_scale_table, + .num_scales = ARRAY_SIZE(bma180_scale_table), + .bw_table = bma180_bw_table, + .num_bw = ARRAY_SIZE(bma180_bw_table), + .int_reset_reg = BMA180_CTRL_REG0, + .int_reset_mask = BMA180_RESET_INT, + .sleep_reg = BMA180_CTRL_REG0, + .sleep_mask = BMA180_SLEEP, + .bw_reg = BMA180_BW_TCS, + .bw_mask = BMA180_BW, + .scale_reg = BMA180_OFFSET_LSB1, + .scale_mask = BMA180_RANGE, + .power_reg = BMA180_TCO_Z, + .power_mask = BMA180_MODE_CONFIG, + .lowpower_val = BMA180_LOW_POWER, + .int_enable_reg = BMA180_CTRL_REG3, + .int_enable_mask = BMA180_NEW_DATA_INT, + .softreset_reg = BMA180_RESET, + .chip_config = bma180_chip_config, + .chip_disable = bma180_chip_disable, }, [BMA250] = { - bma250_channels, ARRAY_SIZE(bma250_channels), - bma250_scale_table, ARRAY_SIZE(bma250_scale_table), - bma250_bw_table, ARRAY_SIZE(bma250_bw_table), - BMA250_INT_RESET_REG, BMA250_INT_RESET_MASK, - BMA250_POWER_REG, BMA250_SUSPEND_MASK, - BMA250_BW_REG, BMA250_BW_MASK, - BMA250_RANGE_REG, BMA250_RANGE_MASK, - BMA250_POWER_REG, BMA250_LOWPOWER_MASK, 1, - BMA250_INT_ENABLE_REG, BMA250_DATA_INTEN_MASK, - BMA250_RESET_REG, - bma250_chip_config, - bma250_chip_disable, + .channels = bma250_channels, + .num_channels = ARRAY_SIZE(bma250_channels), + .scale_table = bma250_scale_table, + .num_scales = ARRAY_SIZE(bma250_scale_table), + .bw_table = bma250_bw_table, + .num_bw = ARRAY_SIZE(bma250_bw_table), + .int_reset_reg = BMA250_INT_RESET_REG, + .int_reset_mask = BMA250_INT_RESET_MASK, + .sleep_reg = BMA250_POWER_REG, + .sleep_mask = BMA250_SUSPEND_MASK, + .bw_reg = BMA250_BW_REG, + .bw_mask = BMA250_BW_MASK, + .scale_reg = BMA250_RANGE_REG, + .scale_mask = BMA250_RANGE_MASK, + .power_reg = BMA250_POWER_REG, + .power_mask = BMA250_LOWPOWER_MASK, + .lowpower_val = 1, + .int_enable_reg = BMA250_INT_ENABLE_REG, + .int_enable_mask = BMA250_DATA_INTEN_MASK, + .softreset_reg = BMA250_RESET_REG, + .chip_config = bma250_chip_config, + .chip_disable = bma250_chip_disable, }, }; From 0c040d1ddce1d5a4d8de215117e8f0792cc62364 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 11 Dec 2019 12:41:47 +0200 Subject: [PATCH 185/353] iio: buffer-dmaengine: Add module information Make sure that the industrialio-buffer-dmaengine has proper license information so it can be build as a module and loaded without tainting the kernel. Signed-off-by: Lars-Peter Clausen Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/buffer/industrialio-buffer-dmaengine.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index b7b5a934e9b2..e0b92f3dec0e 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -206,3 +207,7 @@ void iio_dmaengine_buffer_free(struct iio_buffer *buffer) iio_buffer_put(buffer); } EXPORT_SYMBOL_GPL(iio_dmaengine_buffer_free); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("DMA buffer for the IIO framework"); +MODULE_LICENSE("GPL"); From ac78c6aa4a5dcb1a28eb212fd39d362371b36b06 Mon Sep 17 00:00:00 2001 From: Tomislav Denis Date: Wed, 11 Dec 2019 10:59:44 +0100 Subject: [PATCH 186/353] iio: pressure: Add driver for DLH pressure sensors All Sensors DLH is series of low voltage digital pressure sensors. Additionally to pressure value sensors deliver a temperature value. Sensors can be accessed over I2C and SPI, this driver supports only I2C access. Signed-off-by: Tomislav Denis Signed-off-by: Jonathan Cameron --- MAINTAINERS | 7 + drivers/iio/pressure/Kconfig | 12 ++ drivers/iio/pressure/Makefile | 1 + drivers/iio/pressure/dlhl60d.c | 375 +++++++++++++++++++++++++++++++++ 4 files changed, 395 insertions(+) create mode 100644 drivers/iio/pressure/dlhl60d.c diff --git a/MAINTAINERS b/MAINTAINERS index ee36c19eca1b..0a479418cf5c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -668,6 +668,13 @@ S: Maintained F: Documentation/i2c/busses/i2c-ali1563.rst F: drivers/i2c/busses/i2c-ali1563.c +ALL SENSORS DLH SERIES PRESSURE SENSORS DRIVER +M: Tomislav Denis +W: http://www.allsensors.com/ +S: Maintained +L: linux-iio@vger.kernel.org +F: drivers/iio/pressure/dlhl60d.c + ALLEGRO DVT VIDEO IP CORE DRIVER M: Michael Tretter R: Pengutronix Kernel Team diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index ba420e484787..9c2d9bf8f100 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -53,6 +53,18 @@ config IIO_CROS_EC_BARO To compile this driver as a module, choose M here: the module will be called cros_ec_baro. +config DLHL60D + tristate "All Sensors DLHL60D and DLHL60G low voltage digital pressure sensors" + depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for the All Sensors DLH series + pressure sensors driver. + + To compile this driver as a module, choose M here: the module + will be called dlhl60d. + config DPS310 tristate "Infineon DPS310 pressure and temperature sensor" depends on I2C diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index d8f5ace1f25d..5a79192d8cb5 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_BMP280) += bmp280.o bmp280-objs := bmp280-core.o bmp280-regmap.o obj-$(CONFIG_BMP280_I2C) += bmp280-i2c.o obj-$(CONFIG_BMP280_SPI) += bmp280-spi.o +obj-$(CONFIG_DLHL60D) += dlhl60d.o obj-$(CONFIG_DPS310) += dps310.o obj-$(CONFIG_IIO_CROS_EC_BARO) += cros_ec_baro.o obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o diff --git a/drivers/iio/pressure/dlhl60d.c b/drivers/iio/pressure/dlhl60d.c new file mode 100644 index 000000000000..b8c99e7bd6cf --- /dev/null +++ b/drivers/iio/pressure/dlhl60d.c @@ -0,0 +1,375 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * All Sensors DLH series low voltage digital pressure sensors + * + * Copyright (c) 2019 AVL DiTEST GmbH + * Tomislav Denis + * + * Datasheet: http://www.allsensors.com/cad/DS-0355_Rev_B.PDF + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Commands */ +#define DLH_START_SINGLE 0xAA + +/* Status bits */ +#define DLH_STATUS_OK 0x40 + +/* DLH data format */ +#define DLH_NUM_READ_BYTES 7 +#define DLH_NUM_DATA_BYTES 3 +#define DLH_NUM_PR_BITS 24 +#define DLH_NUM_TEMP_BITS 24 + +/* DLH timings */ +#define DLH_SINGLE_DUT_MS 5 + +enum dhl_ids { + dlhl60d, + dlhl60g, +}; + +struct dlh_info { + u8 osdig; /* digital offset factor */ + unsigned int fss; /* full scale span (inch H2O) */ +}; + +struct dlh_state { + struct i2c_client *client; + struct dlh_info info; + bool use_interrupt; + struct completion completion; + u8 rx_buf[DLH_NUM_READ_BYTES] ____cacheline_aligned; +}; + +static struct dlh_info dlh_info_tbl[] = { + [dlhl60d] = { + .osdig = 2, + .fss = 120, + }, + [dlhl60g] = { + .osdig = 10, + .fss = 60, + }, +}; + + +static int dlh_cmd_start_single(struct dlh_state *st) +{ + int ret; + + ret = i2c_smbus_write_byte(st->client, DLH_START_SINGLE); + if (ret) + dev_err(&st->client->dev, + "%s: I2C write byte failed\n", __func__); + + return ret; +} + +static int dlh_cmd_read_data(struct dlh_state *st) +{ + int ret; + + ret = i2c_master_recv(st->client, st->rx_buf, DLH_NUM_READ_BYTES); + if (ret < 0) { + dev_err(&st->client->dev, + "%s: I2C read block failed\n", __func__); + return ret; + } + + if (st->rx_buf[0] != DLH_STATUS_OK) { + dev_err(&st->client->dev, + "%s: invalid status 0x%02x\n", __func__, st->rx_buf[0]); + return -EBUSY; + } + + return 0; +} + +static int dlh_start_capture_and_read(struct dlh_state *st) +{ + int ret; + + if (st->use_interrupt) + reinit_completion(&st->completion); + + ret = dlh_cmd_start_single(st); + if (ret) + return ret; + + if (st->use_interrupt) { + ret = wait_for_completion_timeout(&st->completion, + msecs_to_jiffies(DLH_SINGLE_DUT_MS)); + if (!ret) { + dev_err(&st->client->dev, + "%s: conversion timed out\n", __func__); + return -ETIMEDOUT; + } + } else { + mdelay(DLH_SINGLE_DUT_MS); + } + + return dlh_cmd_read_data(st); +} + +static int dlh_read_direct(struct dlh_state *st, + unsigned int *pressure, unsigned int *temperature) +{ + int ret; + + ret = dlh_start_capture_and_read(st); + if (ret) + return ret; + + *pressure = get_unaligned_be32(&st->rx_buf[1]) >> 8; + *temperature = get_unaligned_be32(&st->rx_buf[3]) & + GENMASK(DLH_NUM_TEMP_BITS - 1, 0); + + return 0; +} + +static int dlh_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *channel, int *value, + int *value2, long mask) +{ + struct dlh_state *st = iio_priv(indio_dev); + unsigned int pressure, temperature; + int ret; + s64 tmp; + s32 rem; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = dlh_read_direct(st, &pressure, &temperature); + iio_device_release_direct_mode(indio_dev); + if (ret) + return ret; + + switch (channel->type) { + case IIO_PRESSURE: + *value = pressure; + return IIO_VAL_INT; + + case IIO_TEMP: + *value = temperature; + return IIO_VAL_INT; + + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + switch (channel->type) { + case IIO_PRESSURE: + tmp = div_s64(125LL * st->info.fss * 24909 * 100, + 1 << DLH_NUM_PR_BITS); + tmp = div_s64_rem(tmp, 1000000000LL, &rem); + *value = tmp; + *value2 = rem; + return IIO_VAL_INT_PLUS_NANO; + + case IIO_TEMP: + *value = 125 * 1000; + *value2 = DLH_NUM_TEMP_BITS; + return IIO_VAL_FRACTIONAL_LOG2; + + default: + return -EINVAL; + } + case IIO_CHAN_INFO_OFFSET: + switch (channel->type) { + case IIO_PRESSURE: + *value = -125 * st->info.fss * 24909; + *value2 = 100 * st->info.osdig * 100000; + return IIO_VAL_FRACTIONAL; + + case IIO_TEMP: + *value = -40 * 1000; + return IIO_VAL_INT; + + default: + return -EINVAL; + } + } + + return -EINVAL; +} + +static const struct iio_info dlh_info = { + .read_raw = dlh_read_raw, +}; + +static const struct iio_chan_spec dlh_channels[] = { + { + .type = IIO_PRESSURE, + .indexed = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = DLH_NUM_PR_BITS, + .storagebits = 32, + .shift = 8, + .endianness = IIO_BE, + }, + }, { + .type = IIO_TEMP, + .indexed = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_OFFSET), + .scan_index = 1, + .scan_type = { + .sign = 'u', + .realbits = DLH_NUM_TEMP_BITS, + .storagebits = 32, + .shift = 8, + .endianness = IIO_BE, + }, + } +}; + +static irqreturn_t dlh_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct dlh_state *st = iio_priv(indio_dev); + int ret; + unsigned int chn, i = 0; + __be32 tmp_buf[2]; + + ret = dlh_start_capture_and_read(st); + if (ret) + goto out; + + for_each_set_bit(chn, indio_dev->active_scan_mask, + indio_dev->masklength) { + memcpy(tmp_buf + i, + &st->rx_buf[1] + chn * DLH_NUM_DATA_BYTES, + DLH_NUM_DATA_BYTES); + i++; + } + + iio_push_to_buffers(indio_dev, tmp_buf); + +out: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static irqreturn_t dlh_interrupt(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct dlh_state *st = iio_priv(indio_dev); + + complete(&st->completion); + + return IRQ_HANDLED; +}; + +static int dlh_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct dlh_state *st; + struct iio_dev *indio_dev; + int ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE)) { + dev_err(&client->dev, + "adapter doesn't support required i2c functionality\n"); + return -EOPNOTSUPP; + } + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); + if (!indio_dev) { + dev_err(&client->dev, "failed to allocate iio device\n"); + return -ENOMEM; + } + + i2c_set_clientdata(client, indio_dev); + + st = iio_priv(indio_dev); + st->info = dlh_info_tbl[id->driver_data]; + st->client = client; + st->use_interrupt = false; + + indio_dev->name = id->name; + indio_dev->dev.parent = &client->dev; + indio_dev->dev.of_node = client->dev.of_node; + indio_dev->info = &dlh_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = dlh_channels; + indio_dev->num_channels = ARRAY_SIZE(dlh_channels); + + if (client->irq > 0) { + ret = devm_request_threaded_irq(&client->dev, client->irq, + dlh_interrupt, NULL, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + id->name, indio_dev); + if (ret) { + dev_err(&client->dev, "failed to allocate threaded irq"); + return ret; + } + + st->use_interrupt = true; + init_completion(&st->completion); + } + + ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, + NULL, &dlh_trigger_handler, NULL); + if (ret) { + dev_err(&client->dev, "failed to setup iio buffer\n"); + return ret; + } + + ret = devm_iio_device_register(&client->dev, indio_dev); + if (ret) + dev_err(&client->dev, "failed to register iio device\n"); + + return ret; +} + +static const struct of_device_id dlh_of_match[] = { + { .compatible = "asc,dlhl60d" }, + { .compatible = "asc,dlhl60g" }, + {} +}; +MODULE_DEVICE_TABLE(of, dlh_of_match); + +static const struct i2c_device_id dlh_id[] = { + { "dlhl60d", dlhl60d }, + { "dlhl60g", dlhl60g }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dlh_id); + +static struct i2c_driver dlh_driver = { + .driver = { + .name = "dlhl60d", + .of_match_table = dlh_of_match, + }, + .probe = dlh_probe, + .id_table = dlh_id, +}; +module_i2c_driver(dlh_driver); + +MODULE_AUTHOR("Tomislav Denis "); +MODULE_DESCRIPTION("Driver for All Sensors DLH series pressure sensors"); +MODULE_LICENSE("GPL v2"); From 2d983e084b415748d4eb7c6a571635dd609387e1 Mon Sep 17 00:00:00 2001 From: Tomislav Denis Date: Wed, 11 Dec 2019 10:59:45 +0100 Subject: [PATCH 187/353] dt-bindings: Add asc vendor All Sensors Corporation is a manufacturer of MEMS piezoresitive ultra low pressure sensors and pressure transducers. Signed-off-by: Tomislav Denis Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index d3f9690e1e4b..de886aa45823 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -109,6 +109,8 @@ patternProperties: description: Artesyn Embedded Technologies Inc. "^asahi-kasei,.*": description: Asahi Kasei Corp. + "^asc,.*": + description: All Sensors Corporation "^aspeed,.*": description: ASPEED Technology Inc. "^asus,.*": From 2a4fb4def9577cde9d541693a0304e9aab86904b Mon Sep 17 00:00:00 2001 From: Tomislav Denis Date: Wed, 11 Dec 2019 10:59:46 +0100 Subject: [PATCH 188/353] bindings: iio: pressure: Add documentation for dlh driver Add a device tree binding documentation for DLH series pressure sensors. Signed-off-by: Tomislav Denis Signed-off-by: Jonathan Cameron --- .../bindings/iio/pressure/asc,dlhl60d.yaml | 51 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 52 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml diff --git a/Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml b/Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml new file mode 100644 index 000000000000..9f5ca9c42025 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/pressure/asc,dlhl60d.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: All Sensors DLH series low voltage digital pressure sensors + +maintainers: + - Tomislav Denis + +description: | + Bindings for the All Sensors DLH series pressure sensors. + + Specifications about the sensors can be found at: + http://www.allsensors.com/cad/DS-0355_Rev_B.PDF + +properties: + compatible: + enum: + - asc,dlhl60d + - asc,dlhl60g + + reg: + description: I2C device address + maxItems: 1 + + interrupts: + description: interrupt mapping for EOC(data ready) pin + maxItems: 1 + +required: + - compatible + - reg + +examples: + - | + #include + + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + + pressure@29 { + compatible = "asc,dlhl60d"; + reg = <0x29>; + interrupt-parent = <&gpio0>; + interrupts = <10 IRQ_TYPE_EDGE_RISING>; + }; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index 0a479418cf5c..ec05a06d7ddb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -674,6 +674,7 @@ W: http://www.allsensors.com/ S: Maintained L: linux-iio@vger.kernel.org F: drivers/iio/pressure/dlhl60d.c +F: Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml ALLEGRO DVT VIDEO IP CORE DRIVER M: Michael Tretter From 4538c185680996d7328beac629dbdb7dd3f8f34e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 11 Dec 2019 13:56:15 +0200 Subject: [PATCH 189/353] iio: buffer-dmaengine: Report buffer length requirements The dmaengine buffer has some length alignment requirements that can differ from platform to platform. If the length alignment requirements are not met unexpected behavior like dropping of samples can occur. Currently these requirements are not reported and applications need to know the requirements of the platform by some out-of-band means. Add a new buffer attribute that reports the length alignment requirements called `length_align_bytes`. The reported length alignment is in bytes that means the buffer length alignment in sample sets depends on the number of enabled channels and the bytes per channel. Applications using this attribute to determine the buffer size requirements need to consider this. Signed-off-by: Lars-Peter Clausen Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- .../ABI/testing/sysfs-bus-iio-dma-buffer | 19 +++++++++++++++++ .../buffer/industrialio-buffer-dmaengine.c | 21 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-dma-buffer diff --git a/Documentation/ABI/testing/sysfs-bus-iio-dma-buffer b/Documentation/ABI/testing/sysfs-bus-iio-dma-buffer new file mode 100644 index 000000000000..d526e6571001 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-dma-buffer @@ -0,0 +1,19 @@ +What: /sys/bus/iio/devices/iio:deviceX/buffer/length_align_bytes +KernelVersion: 5.4 +Contact: linux-iio@vger.kernel.org +Description: + DMA buffers tend to have a alignment requirement for the + buffers. If this alignment requirement is not met samples might + be dropped from the buffer. + + This property reports the alignment requirements in bytes. + This means that the buffer size in bytes needs to be a integer + multiple of the number reported by this file. + + The alignment requirements in number of sample sets will depend + on the enabled channels and the bytes per channel. This means + that the alignment requirement in samples sets might change + depending on which and how many channels are enabled. Whereas + the alignment requirement reported in bytes by this property + will remain static and does not depend on which channels are + enabled. diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index e0b92f3dec0e..744abd7e1269 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -126,6 +127,24 @@ static const struct iio_dma_buffer_ops iio_dmaengine_default_ops = { .abort = iio_dmaengine_buffer_abort, }; +static ssize_t iio_dmaengine_buffer_get_length_align(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct dmaengine_buffer *dmaengine_buffer = + iio_buffer_to_dmaengine_buffer(indio_dev->buffer); + + return sprintf(buf, "%u\n", dmaengine_buffer->align); +} + +static IIO_DEVICE_ATTR(length_align_bytes, 0444, + iio_dmaengine_buffer_get_length_align, NULL, 0); + +static const struct attribute *iio_dmaengine_buffer_attrs[] = { + &iio_dev_attr_length_align_bytes.dev_attr.attr, + NULL, +}; + /** * iio_dmaengine_buffer_alloc() - Allocate new buffer which uses DMAengine * @dev: Parent device for the buffer @@ -179,6 +198,8 @@ struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, iio_dma_buffer_init(&dmaengine_buffer->queue, chan->device->dev, &iio_dmaengine_default_ops); + iio_buffer_set_attrs(&dmaengine_buffer->queue.buffer, + iio_dmaengine_buffer_attrs); dmaengine_buffer->queue.buffer.access = &iio_dmaengine_buffer_ops; From f6d4033d2a14b454680585d4ab974d163fcd7a47 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 11 Dec 2019 12:43:00 +0200 Subject: [PATCH 190/353] iio: buffer: rename 'read_first_n' callback to 'read' It is implied that 'read' will read the first n bytes and not e.g. bytes only from offsets within the buffer that are a prime number. This change is non-functional, mostly just a rename. A secondary intent with this patch is to make room later to add a write callback. Signed-off-by: Lars-Peter Clausen Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/buffer/industrialio-buffer-dma.c | 2 +- drivers/iio/buffer/industrialio-buffer-dmaengine.c | 2 +- drivers/iio/buffer/kfifo_buf.c | 5 ++--- drivers/iio/iio_core.h | 8 ++++---- drivers/iio/industrialio-buffer.c | 10 +++++----- drivers/iio/industrialio-core.c | 2 +- include/linux/iio/buffer_impl.h | 6 ++---- 7 files changed, 16 insertions(+), 19 deletions(-) diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c b/drivers/iio/buffer/industrialio-buffer-dma.c index 90cf6e586b10..a74bd9c0587c 100644 --- a/drivers/iio/buffer/industrialio-buffer-dma.c +++ b/drivers/iio/buffer/industrialio-buffer-dma.c @@ -476,7 +476,7 @@ static struct iio_dma_buffer_block *iio_dma_buffer_dequeue( * @n: Number of bytes to read * @user_buffer: Userspace buffer to copy the data to * - * Should be used as the read_first_n callback for iio_buffer_access_ops + * Should be used as the read callback for iio_buffer_access_ops * struct for DMA buffers. */ int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n, diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index 744abd7e1269..b129693af0fd 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -109,7 +109,7 @@ static void iio_dmaengine_buffer_release(struct iio_buffer *buf) } static const struct iio_buffer_access_funcs iio_dmaengine_buffer_ops = { - .read_first_n = iio_dma_buffer_read, + .read = iio_dma_buffer_read, .set_bytes_per_datum = iio_dma_buffer_set_bytes_per_datum, .set_length = iio_dma_buffer_set_length, .request_update = iio_dma_buffer_request_update, diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c index e78fc0834e6b..3150f8ab984b 100644 --- a/drivers/iio/buffer/kfifo_buf.c +++ b/drivers/iio/buffer/kfifo_buf.c @@ -98,8 +98,7 @@ static int iio_store_to_kfifo(struct iio_buffer *r, return 0; } -static int iio_read_first_n_kfifo(struct iio_buffer *r, - size_t n, char __user *buf) +static int iio_read_kfifo(struct iio_buffer *r, size_t n, char __user *buf) { int ret, copied; struct iio_kfifo *kf = iio_to_kfifo(r); @@ -141,7 +140,7 @@ static void iio_kfifo_buffer_release(struct iio_buffer *buffer) static const struct iio_buffer_access_funcs kfifo_access_funcs = { .store_to = &iio_store_to_kfifo, - .read_first_n = &iio_read_first_n_kfifo, + .read = &iio_read_kfifo, .data_available = iio_kfifo_buf_data_available, .request_update = &iio_request_update_kfifo, .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h index 159ea3f8c02b..fd9a5f1d5e51 100644 --- a/drivers/iio/iio_core.h +++ b/drivers/iio/iio_core.h @@ -42,14 +42,14 @@ struct poll_table_struct; __poll_t iio_buffer_poll(struct file *filp, struct poll_table_struct *wait); -ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, - size_t n, loff_t *f_ps); +ssize_t iio_buffer_read_outer(struct file *filp, char __user *buf, + size_t n, loff_t *f_ps); int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev); void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev); #define iio_buffer_poll_addr (&iio_buffer_poll) -#define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer) +#define iio_buffer_read_outer_addr (&iio_buffer_read_outer) void iio_disable_all_buffers(struct iio_dev *indio_dev); void iio_buffer_wakeup_poll(struct iio_dev *indio_dev); @@ -57,7 +57,7 @@ void iio_buffer_wakeup_poll(struct iio_dev *indio_dev); #else #define iio_buffer_poll_addr NULL -#define iio_buffer_read_first_n_outer_addr NULL +#define iio_buffer_read_outer_addr NULL static inline int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) { diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index c193d64e5217..dbbf0cf4cac9 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -87,7 +87,7 @@ static bool iio_buffer_ready(struct iio_dev *indio_dev, struct iio_buffer *buf, } /** - * iio_buffer_read_first_n_outer() - chrdev read for buffer access + * iio_buffer_read_outer() - chrdev read for buffer access * @filp: File structure pointer for the char device * @buf: Destination buffer for iio buffer read * @n: First n bytes to read @@ -99,8 +99,8 @@ static bool iio_buffer_ready(struct iio_dev *indio_dev, struct iio_buffer *buf, * Return: negative values corresponding to error codes or ret != 0 * for ending the reading activity **/ -ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, - size_t n, loff_t *f_ps) +ssize_t iio_buffer_read_outer(struct file *filp, char __user *buf, + size_t n, loff_t *f_ps) { struct iio_dev *indio_dev = filp->private_data; struct iio_buffer *rb = indio_dev->buffer; @@ -112,7 +112,7 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, if (!indio_dev->info) return -ENODEV; - if (!rb || !rb->access->read_first_n) + if (!rb || !rb->access->read) return -EINVAL; datum_size = rb->bytes_per_datum; @@ -147,7 +147,7 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, continue; } - ret = rb->access->read_first_n(rb, n, buf); + ret = rb->access->read(rb, n, buf); if (ret == 0 && (filp->f_flags & O_NONBLOCK)) ret = -EAGAIN; } while (ret == 0); diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index fa2c3b321bfd..2c107ac61de3 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1632,7 +1632,7 @@ static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } static const struct file_operations iio_buffer_fileops = { - .read = iio_buffer_read_first_n_outer_addr, + .read = iio_buffer_read_outer_addr, .release = iio_chrdev_release, .open = iio_chrdev_open, .poll = iio_buffer_poll_addr, diff --git a/include/linux/iio/buffer_impl.h b/include/linux/iio/buffer_impl.h index d1171db23742..a4d2d8061ef6 100644 --- a/include/linux/iio/buffer_impl.h +++ b/include/linux/iio/buffer_impl.h @@ -18,7 +18,7 @@ struct iio_buffer; /** * struct iio_buffer_access_funcs - access functions for buffers. * @store_to: actually store stuff to the buffer - * @read_first_n: try to get a specified number of bytes (must exist) + * @read: try to get a specified number of bytes (must exist) * @data_available: indicates how much data is available for reading from * the buffer. * @request_update: if a parameter change has been marked, update underlying @@ -45,9 +45,7 @@ struct iio_buffer; **/ struct iio_buffer_access_funcs { int (*store_to)(struct iio_buffer *buffer, const void *data); - int (*read_first_n)(struct iio_buffer *buffer, - size_t n, - char __user *buf); + int (*read)(struct iio_buffer *buffer, size_t n, char __user *buf); size_t (*data_available)(struct iio_buffer *buffer); int (*request_update)(struct iio_buffer *buffer); From 57b8879c0c1af5ac4cfc9dd1260d40b13dd6027d Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Fri, 6 Dec 2019 11:00:58 +0100 Subject: [PATCH 191/353] dt-bindings: iio: adc: convert sd modulator to json-schema Convert the sigma delta modulator bindings to DT schema format using json-schema. Signed-off-by: Olivier Moysan Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../iio/adc/sigma-delta-modulator.txt | 13 ------- .../iio/adc/sigma-delta-modulator.yaml | 37 +++++++++++++++++++ 2 files changed, 37 insertions(+), 13 deletions(-) delete mode 100644 Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt create mode 100644 Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt deleted file mode 100644 index 59b92cd32552..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt +++ /dev/null @@ -1,13 +0,0 @@ -Device-Tree bindings for sigma delta modulator - -Required properties: -- compatible: should be "ads1201", "sd-modulator". "sd-modulator" can be use - as a generic SD modulator if modulator not specified in compatible list. -- #io-channel-cells = <0>: See the IIO bindings section "IIO consumers". - -Example node: - - ads1202: adc { - compatible = "sd-modulator"; - #io-channel-cells = <0>; - }; diff --git a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml new file mode 100644 index 000000000000..a390343d0c2a --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/sigma-delta-modulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Device-Tree bindings for sigma delta modulator + +maintainers: + - Arnaud Pouliquen + +properties: + compatible: + description: | + "sd-modulator" can be used as a generic SD modulator, + if the modulator is not specified in the compatible list. + enum: + - sd-modulator + - ads1201 + + '#io-channel-cells': + const: 0 + +required: + - compatible + - '#io-channel-cells' + +additionalProperties: false + +examples: + - | + ads1202: adc { + compatible = "sd-modulator"; + #io-channel-cells = <0>; + }; + +... From ab2ecec63320f8de5e0b15be6b427312e2e59f24 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 9 Dec 2019 20:28:04 +0200 Subject: [PATCH 192/353] iio: pressure: bmp280: Drop ACPI support There is no evidence of officially registered ACPI IDs for these devices. Thus, revert ACPI support from the driver. All authors of the respective changes are being informed here: d5c94568cc1d ("iio: add bmp280 pressure and temperature driver") 6dba72eca7fb ("iio: pressure: bmp280: add support for BMP180") 14beaa8f5ab1 ("iio: pressure: bmp280: add humidity support") Above seems a cargo cult without paying attention to how ACPI IDs are being allocated. Cc: Vlad Dogaru Cc: Akinobu Mita Cc: Matt Ranostay Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/bmp280-i2c.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c index 3109c8e2cc11..06f90853c141 100644 --- a/drivers/iio/pressure/bmp280-i2c.c +++ b/drivers/iio/pressure/bmp280-i2c.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only #include #include -#include #include #include @@ -38,15 +37,6 @@ static int bmp280_i2c_probe(struct i2c_client *client, client->irq); } -static const struct acpi_device_id bmp280_acpi_i2c_match[] = { - {"BMP0280", BMP280_CHIP_ID }, - {"BMP0180", BMP180_CHIP_ID }, - {"BMP0085", BMP180_CHIP_ID }, - {"BME0280", BME280_CHIP_ID }, - { }, -}; -MODULE_DEVICE_TABLE(acpi, bmp280_acpi_i2c_match); - #ifdef CONFIG_OF static const struct of_device_id bmp280_of_i2c_match[] = { { .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID }, @@ -72,7 +62,6 @@ MODULE_DEVICE_TABLE(i2c, bmp280_i2c_id); static struct i2c_driver bmp280_i2c_driver = { .driver = { .name = "bmp280", - .acpi_match_table = ACPI_PTR(bmp280_acpi_i2c_match), .of_match_table = of_match_ptr(bmp280_of_i2c_match), .pm = &bmp280_dev_pm_ops, }, From ae9685992cd542b7881ff1d64a4bfd7ba509c3bb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 9 Dec 2019 20:28:05 +0200 Subject: [PATCH 193/353] iio: pressure: bmp280: Allow device to be enumerated from ACPI There is no need to limit the driver use by OF/platform code. In this case we simple remove redundant OF parts from the code. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/bmp280-i2c.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c index 06f90853c141..8b03ea15c0d0 100644 --- a/drivers/iio/pressure/bmp280-i2c.c +++ b/drivers/iio/pressure/bmp280-i2c.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only #include #include -#include #include #include "bmp280.h" @@ -37,7 +36,6 @@ static int bmp280_i2c_probe(struct i2c_client *client, client->irq); } -#ifdef CONFIG_OF static const struct of_device_id bmp280_of_i2c_match[] = { { .compatible = "bosch,bme280", .data = (void *)BME280_CHIP_ID }, { .compatible = "bosch,bmp280", .data = (void *)BMP280_CHIP_ID }, @@ -46,9 +44,6 @@ static const struct of_device_id bmp280_of_i2c_match[] = { { }, }; MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match); -#else -#define bmp280_of_i2c_match NULL -#endif static const struct i2c_device_id bmp280_i2c_id[] = { {"bmp280", BMP280_CHIP_ID }, @@ -62,7 +57,7 @@ MODULE_DEVICE_TABLE(i2c, bmp280_i2c_id); static struct i2c_driver bmp280_i2c_driver = { .driver = { .name = "bmp280", - .of_match_table = of_match_ptr(bmp280_of_i2c_match), + .of_match_table = bmp280_of_i2c_match, .pm = &bmp280_dev_pm_ops, }, .probe = bmp280_i2c_probe, From c1d1c4a62db5c4745b9e15cfee0daf0f774f73fc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 11 Dec 2019 22:38:19 +0100 Subject: [PATCH 194/353] iio: accel: bma180: BMA254 support This adds support for the BMA254 variant of this accelerometer. The only difference for the simple IIO driver is that values are 12 bit and the temperature offset differs by 1 degree. Whilst wildcards in naming are normally frowned upon: The cases where I have labeled variables "25x" is where the models are identical, so as to make things easier for people that want to add support for BMA253 and BMA255. Cc: Peter Meerwald Cc: Oleksandr Kravchenko Cc: devicetree@vger.kernel.org Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/accel/bma180.txt | 7 +- drivers/iio/accel/Kconfig | 4 +- drivers/iio/accel/bma180.c | 108 +++++++++++++++--- 3 files changed, 100 insertions(+), 19 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/accel/bma180.txt b/Documentation/devicetree/bindings/iio/accel/bma180.txt index 3b25b4c4d446..f53237270b32 100644 --- a/Documentation/devicetree/bindings/iio/accel/bma180.txt +++ b/Documentation/devicetree/bindings/iio/accel/bma180.txt @@ -1,11 +1,14 @@ -* Bosch BMA180 / BMA250 triaxial acceleration sensor +* Bosch BMA180 / BMA25x triaxial acceleration sensor http://omapworld.com/BMA180_111_1002839.pdf http://ae-bst.resource.bosch.com/media/products/dokumente/bma250/bst-bma250-ds002-05.pdf Required properties: - - compatible : should be "bosch,bma180" or "bosch,bma250" + - compatible : should be one of: + "bosch,bma180" + "bosch,bma250" + "bosch,bma254" - reg : the I2C address of the sensor Optional properties: diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 670e60568033..5d91a6dda894 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -89,13 +89,13 @@ config ADXL372_I2C module will be called adxl372_i2c. config BMA180 - tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver" + tristate "Bosch BMA180/BMA25x 3-Axis Accelerometer Driver" depends on I2C select IIO_BUFFER select IIO_TRIGGERED_BUFFER help Say Y here if you want to build a driver for the Bosch BMA180 or - BMA250 triaxial acceleration sensor. + BMA25x triaxial acceleration sensor. To compile this driver as a module, choose M here: the module will be called bma180. diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 45dd096c0220..fcd91d5f05fd 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -9,6 +9,7 @@ * SPI is not supported by driver * BMA180: 7-bit I2C slave address 0x40 or 0x41 * BMA250: 7-bit I2C slave address 0x18 or 0x19 + * BMA254: 7-bit I2C slave address 0x18 or 0x19 */ #include @@ -34,17 +35,20 @@ enum chip_ids { BMA180, BMA250, + BMA254, }; struct bma180_data; struct bma180_part_info { + u8 chip_id; const struct iio_chan_spec *channels; unsigned int num_channels; const int *scale_table; unsigned int num_scales; const int *bw_table; unsigned int num_bw; + int center_temp; u8 int_reset_reg, int_reset_mask; u8 sleep_reg, sleep_mask; @@ -52,6 +56,7 @@ struct bma180_part_info { u8 scale_reg, scale_mask; u8 power_reg, power_mask, lowpower_val; u8 int_enable_reg, int_enable_mask; + u8 int_map_reg, int_enable_dataready_int1_mask; u8 softreset_reg; int (*chip_config)(struct bma180_data *data); @@ -90,6 +95,8 @@ struct bma180_part_info { #define BMA180_RESET_VAL 0xb6 #define BMA180_ID_REG_VAL 0x03 +#define BMA250_ID_REG_VAL 0x03 +#define BMA254_ID_REG_VAL 0xfa /* 250 decimal */ /* Chip power modes */ #define BMA180_LOW_POWER 0x03 @@ -110,6 +117,23 @@ struct bma180_part_info { #define BMA250_INT1_DATA_MASK BIT(0) #define BMA250_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ +#define BMA254_RANGE_REG 0x0f +#define BMA254_BW_REG 0x10 +#define BMA254_POWER_REG 0x11 +#define BMA254_RESET_REG 0x14 +#define BMA254_INT_ENABLE_REG 0x17 +#define BMA254_INT_MAP_REG 0x1a +#define BMA254_INT_RESET_REG 0x21 + +#define BMA254_RANGE_MASK GENMASK(3, 0) /* Range of accel values */ +#define BMA254_BW_MASK GENMASK(4, 0) /* Accel bandwidth */ +#define BMA254_SUSPEND_MASK BIT(7) /* chip will sleep */ +#define BMA254_LOWPOWER_MASK BIT(6) +#define BMA254_DATA_INTEN_MASK BIT(4) +#define BMA254_INT2_DATA_MASK BIT(7) +#define BMA254_INT1_DATA_MASK BIT(0) +#define BMA254_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ + struct bma180_data { struct regulator *vdd_supply; struct regulator *vddio_supply; @@ -135,8 +159,8 @@ enum bma180_chan { static int bma180_bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */ static int bma180_scale_table[] = { 1275, 1863, 2452, 3727, 4903, 9709, 19417 }; -static int bma250_bw_table[] = { 8, 16, 31, 63, 125, 250 }; /* Hz */ -static int bma250_scale_table[] = { 0, 0, 0, 38344, 0, 76590, 0, 0, 153180, 0, +static int bma25x_bw_table[] = { 8, 16, 31, 63, 125, 250 }; /* Hz */ +static int bma25x_scale_table[] = { 0, 0, 0, 38344, 0, 76590, 0, 0, 153180, 0, 0, 0, 306458 }; static int bma180_get_data_reg(struct bma180_data *data, enum bma180_chan chan) @@ -310,8 +334,11 @@ static int bma180_chip_init(struct bma180_data *data) if (ret < 0) return ret; - if (ret != BMA180_ID_REG_VAL) + if (ret != data->part_info->chip_id) { + dev_err(&data->client->dev, "wrong chip ID %d expected %d\n", + ret, data->part_info->chip_id); return -ENODEV; + } ret = bma180_soft_reset(data); if (ret) @@ -358,7 +385,7 @@ err: return ret; } -static int bma250_chip_config(struct bma180_data *data) +static int bma25x_chip_config(struct bma180_data *data) { int ret = bma180_chip_init(data); @@ -370,8 +397,12 @@ static int bma250_chip_config(struct bma180_data *data) ret = bma180_set_scale(data, 38344); /* 2 G */ if (ret) goto err; - ret = bma180_set_bits(data, BMA250_INT_MAP_REG, - BMA250_INT1_DATA_MASK, 1); + /* + * This enables dataready interrupt on the INT1 pin + * FIXME: support using the INT2 pin + */ + ret = bma180_set_bits(data, data->part_info->int_map_reg, + data->part_info->int_enable_dataready_int1_mask, 1); if (ret) goto err; @@ -397,7 +428,7 @@ err: dev_err(&data->client->dev, "failed to disable the chip\n"); } -static void bma250_chip_disable(struct bma180_data *data) +static void bma25x_chip_disable(struct bma180_data *data) { if (bma180_set_new_data_intr_state(data, false)) goto err; @@ -500,7 +531,7 @@ static int bma180_read_raw(struct iio_dev *indio_dev, return -EINVAL; } case IIO_CHAN_INFO_OFFSET: - *val = 48; /* 0 LSB @ 24 degree C */ + *val = data->part_info->center_temp; return IIO_VAL_INT; default: return -EINVAL; @@ -630,14 +661,24 @@ static const struct iio_chan_spec bma250_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(4), }; +static const struct iio_chan_spec bma254_channels[] = { + BMA180_ACC_CHANNEL(X, 12), + BMA180_ACC_CHANNEL(Y, 12), + BMA180_ACC_CHANNEL(Z, 12), + BMA180_TEMP_CHANNEL, + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + static const struct bma180_part_info bma180_part_info[] = { [BMA180] = { + .chip_id = BMA180_ID_REG_VAL, .channels = bma180_channels, .num_channels = ARRAY_SIZE(bma180_channels), .scale_table = bma180_scale_table, .num_scales = ARRAY_SIZE(bma180_scale_table), .bw_table = bma180_bw_table, .num_bw = ARRAY_SIZE(bma180_bw_table), + .center_temp = 48, /* 0 LSB @ 24 degree C */ .int_reset_reg = BMA180_CTRL_REG0, .int_reset_mask = BMA180_RESET_INT, .sleep_reg = BMA180_CTRL_REG0, @@ -656,12 +697,14 @@ static const struct bma180_part_info bma180_part_info[] = { .chip_disable = bma180_chip_disable, }, [BMA250] = { + .chip_id = BMA250_ID_REG_VAL, .channels = bma250_channels, .num_channels = ARRAY_SIZE(bma250_channels), - .scale_table = bma250_scale_table, - .num_scales = ARRAY_SIZE(bma250_scale_table), - .bw_table = bma250_bw_table, - .num_bw = ARRAY_SIZE(bma250_bw_table), + .scale_table = bma25x_scale_table, + .num_scales = ARRAY_SIZE(bma25x_scale_table), + .bw_table = bma25x_bw_table, + .num_bw = ARRAY_SIZE(bma25x_bw_table), + .center_temp = 48, /* 0 LSB @ 24 degree C */ .int_reset_reg = BMA250_INT_RESET_REG, .int_reset_mask = BMA250_INT_RESET_MASK, .sleep_reg = BMA250_POWER_REG, @@ -675,9 +718,39 @@ static const struct bma180_part_info bma180_part_info[] = { .lowpower_val = 1, .int_enable_reg = BMA250_INT_ENABLE_REG, .int_enable_mask = BMA250_DATA_INTEN_MASK, + .int_map_reg = BMA250_INT_MAP_REG, + .int_enable_dataready_int1_mask = BMA250_INT1_DATA_MASK, .softreset_reg = BMA250_RESET_REG, - .chip_config = bma250_chip_config, - .chip_disable = bma250_chip_disable, + .chip_config = bma25x_chip_config, + .chip_disable = bma25x_chip_disable, + }, + [BMA254] = { + .chip_id = BMA254_ID_REG_VAL, + .channels = bma254_channels, + .num_channels = ARRAY_SIZE(bma254_channels), + .scale_table = bma25x_scale_table, + .num_scales = ARRAY_SIZE(bma25x_scale_table), + .bw_table = bma25x_bw_table, + .num_bw = ARRAY_SIZE(bma25x_bw_table), + .center_temp = 46, /* 0 LSB @ 23 degree C */ + .int_reset_reg = BMA254_INT_RESET_REG, + .int_reset_mask = BMA254_INT_RESET_MASK, + .sleep_reg = BMA254_POWER_REG, + .sleep_mask = BMA254_SUSPEND_MASK, + .bw_reg = BMA254_BW_REG, + .bw_mask = BMA254_BW_MASK, + .scale_reg = BMA254_RANGE_REG, + .scale_mask = BMA254_RANGE_MASK, + .power_reg = BMA254_POWER_REG, + .power_mask = BMA254_LOWPOWER_MASK, + .lowpower_val = 1, + .int_enable_reg = BMA254_INT_ENABLE_REG, + .int_enable_mask = BMA254_DATA_INTEN_MASK, + .int_map_reg = BMA254_INT_MAP_REG, + .int_enable_dataready_int1_mask = BMA254_INT1_DATA_MASK, + .softreset_reg = BMA254_RESET_REG, + .chip_config = bma25x_chip_config, + .chip_disable = bma25x_chip_disable, }, }; @@ -919,6 +992,7 @@ static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume); static const struct i2c_device_id bma180_ids[] = { { "bma180", BMA180 }, { "bma250", BMA250 }, + { "bma254", BMA254 }, { } }; @@ -933,6 +1007,10 @@ static const struct of_device_id bma180_of_match[] = { .compatible = "bosch,bma250", .data = (void *)BMA250 }, + { + .compatible = "bosch,bma254", + .data = (void *)BMA254 + }, { } }; MODULE_DEVICE_TABLE(of, bma180_of_match); @@ -952,5 +1030,5 @@ module_i2c_driver(bma180_driver); MODULE_AUTHOR("Kravchenko Oleksandr "); MODULE_AUTHOR("Texas Instruments, Inc."); -MODULE_DESCRIPTION("Bosch BMA180/BMA250 triaxial acceleration sensor"); +MODULE_DESCRIPTION("Bosch BMA180/BMA25x triaxial acceleration sensor"); MODULE_LICENSE("GPL"); From d7a336d67ab5443a0ef14b8335d139e855e8a682 Mon Sep 17 00:00:00 2001 From: Aditya Pakki Date: Thu, 19 Dec 2019 11:21:11 -0600 Subject: [PATCH 195/353] staging: kpc2000: remove unnecessary assertions in kpc_dma_transfer In kpc_dma_transfer(), the assertion that priv is NULL and priv->ldev is NULL, are never satisfied. The two callers of the function, dereference the fields before the function is called. This patch removes the two BUG_ON calls. Signed-off-by: Aditya Pakki Link: https://lore.kernel.org/r/20191219172118.17456-1-pakki001@umn.edu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/kpc2000/kpc_dma/fileops.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c index cb52bd9a6d2f..40525540dde6 100644 --- a/drivers/staging/kpc2000/kpc_dma/fileops.c +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c @@ -49,9 +49,7 @@ static int kpc_dma_transfer(struct dev_private_data *priv, u64 dma_addr; u64 user_ctl; - BUG_ON(priv == NULL); ldev = priv->ldev; - BUG_ON(ldev == NULL); acd = kzalloc(sizeof(*acd), GFP_KERNEL); if (!acd) { From d1e10852aa63d840dd4d373cd6ab421d3de022d5 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 20 Dec 2019 18:44:13 +0100 Subject: [PATCH 196/353] staging: rtl8188eu: use break to exit while loop The variable bContinual in Efuse_PgPacketRead() is only used to break out of a while loop. Remove the variable and use break instead. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20191220174413.13913-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_efuse.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index d9b0f9e6235c..0b86ae8338d9 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -402,7 +402,6 @@ static u16 Efuse_GetCurrentSize(struct adapter *pAdapter) int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) { u8 ReadState = PG_STATE_HEADER; - int bContinual = true; int bDataEmpty = true; u8 efuse_data, word_cnts = 0; u16 efuse_addr = 0; @@ -422,7 +421,7 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) /* Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */ /* Skip dummy parts to prevent unexpected data read from Efuse. */ /* By pass right now. 2009.02.19. */ - while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) { + while (AVAILABLE_EFUSE_ADDR(efuse_addr)) { /* Header Read ------------- */ if (ReadState & PG_STATE_HEADER) { if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) { @@ -464,7 +463,7 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) ReadState = PG_STATE_HEADER; } } else { - bContinual = false; + break; } } else if (ReadState & PG_STATE_DATA) { /* Data section Read ------------- */ From 97806d3602efdf78f32beb7c34493518ba150b97 Mon Sep 17 00:00:00 2001 From: Amir Mahdi Ghorbanian Date: Mon, 30 Dec 2019 10:55:20 -0500 Subject: [PATCH 197/353] staging: vt6656: remove unnecessary parenthesis Remove unnecessary parenthesis to abide by kernel coding-style. Signed-off-by: Amir Mahdi Ghorbanian Link: https://lore.kernel.org/r/20191230155520.GA27072@user-ThinkPad-X230 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/baseband.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c index 8d19ae71e7cc..25fb19fadc57 100644 --- a/drivers/staging/vt6656/baseband.c +++ b/drivers/staging/vt6656/baseband.c @@ -381,8 +381,8 @@ int vnt_vt3184_init(struct vnt_private *priv) dev_dbg(&priv->usb->dev, "RF Type %d\n", priv->rf_type); - if ((priv->rf_type == RF_AL2230) || - (priv->rf_type == RF_AL2230S)) { + if (priv->rf_type == RF_AL2230 || + priv->rf_type == RF_AL2230S) { priv->bb_rx_conf = vnt_vt3184_al2230[10]; length = sizeof(vnt_vt3184_al2230); addr = vnt_vt3184_al2230; @@ -461,8 +461,8 @@ int vnt_vt3184_init(struct vnt_private *priv) if (ret) goto end; - if ((priv->rf_type == RF_VT3226) || - (priv->rf_type == RF_VT3342A0)) { + if (priv->rf_type == RF_VT3226 || + priv->rf_type == RF_VT3342A0) { ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_ITRTMSET, 0x23); if (ret) From 5f33771fb0ac484d6e8cc34cb1e27c37442cd0db Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Fri, 3 Jan 2020 09:13:45 +0800 Subject: [PATCH 198/353] staging: exfat: add STAGING prefix to config names Add STAGING prefix to config names to avoid collsion with fs/exfat config. Signed-off-by: Namjae Jeon Link: https://lore.kernel.org/r/20200103011345.25245-1-namjae.jeon@samsung.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Makefile | 2 +- drivers/staging/exfat/Kconfig | 26 +++++++-------- drivers/staging/exfat/Makefile | 2 +- drivers/staging/exfat/exfat.h | 14 ++++---- drivers/staging/exfat/exfat_blkdev.c | 12 +++---- drivers/staging/exfat/exfat_core.c | 8 ++--- drivers/staging/exfat/exfat_super.c | 50 ++++++++++++++-------------- 7 files changed, 57 insertions(+), 57 deletions(-) diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 463aef6a18ef..fdd03fd6e704 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -48,7 +48,7 @@ obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ obj-$(CONFIG_KPC2000) += kpc2000/ obj-$(CONFIG_UWB) += uwb/ obj-$(CONFIG_USB_WUSB) += wusbcore/ -obj-$(CONFIG_EXFAT_FS) += exfat/ +obj-$(CONFIG_STAGING_EXFAT_FS) += exfat/ obj-$(CONFIG_QLGE) += qlge/ obj-$(CONFIG_NET_VENDOR_HP) += hp/ obj-$(CONFIG_WFX) += wfx/ diff --git a/drivers/staging/exfat/Kconfig b/drivers/staging/exfat/Kconfig index 0130019cbec2..292a19dfcaf5 100644 --- a/drivers/staging/exfat/Kconfig +++ b/drivers/staging/exfat/Kconfig @@ -1,41 +1,41 @@ # SPDX-License-Identifier: GPL-2.0 -config EXFAT_FS +config STAGING_EXFAT_FS tristate "exFAT fs support" depends on BLOCK select NLS help This adds support for the exFAT file system. -config EXFAT_DISCARD +config STAGING_EXFAT_DISCARD bool "enable discard support" - depends on EXFAT_FS + depends on STAGING_EXFAT_FS default y -config EXFAT_DELAYED_SYNC +config STAGING_EXFAT_DELAYED_SYNC bool "enable delayed sync" - depends on EXFAT_FS + depends on STAGING_EXFAT_FS default n -config EXFAT_KERNEL_DEBUG +config STAGING_EXFAT_KERNEL_DEBUG bool "enable kernel debug features via ioctl" - depends on EXFAT_FS + depends on STAGING_EXFAT_FS default n -config EXFAT_DEBUG_MSG +config STAGING_EXFAT_DEBUG_MSG bool "print debug messages" - depends on EXFAT_FS + depends on STAGING_EXFAT_FS default n -config EXFAT_DEFAULT_CODEPAGE +config STAGING_EXFAT_DEFAULT_CODEPAGE int "Default codepage for exFAT" default 437 - depends on EXFAT_FS + depends on STAGING_EXFAT_FS help This option should be set to the codepage of your exFAT filesystems. -config EXFAT_DEFAULT_IOCHARSET +config STAGING_EXFAT_DEFAULT_IOCHARSET string "Default iocharset for exFAT" default "utf8" - depends on EXFAT_FS + depends on STAGING_EXFAT_FS help Set this to the default input/output character set you'd like exFAT to use. diff --git a/drivers/staging/exfat/Makefile b/drivers/staging/exfat/Makefile index 6c90aec83feb..057556eeca0c 100644 --- a/drivers/staging/exfat/Makefile +++ b/drivers/staging/exfat/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-or-later -obj-$(CONFIG_EXFAT_FS) += exfat.o +obj-$(CONFIG_STAGING_EXFAT_FS) += exfat.o exfat-y := exfat_core.o \ exfat_super.o \ diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h index 51c665a924b7..3865c17027ce 100644 --- a/drivers/staging/exfat/exfat.h +++ b/drivers/staging/exfat/exfat.h @@ -9,7 +9,7 @@ #include #include -#ifdef CONFIG_EXFAT_KERNEL_DEBUG +#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG /* For Debugging Purpose */ /* IOCTL code 'f' used by * - file systems typically #0~0x1F @@ -22,9 +22,9 @@ #define EXFAT_DEBUGFLAGS_INVALID_UMOUNT 0x01 #define EXFAT_DEBUGFLAGS_ERROR_RW 0x02 -#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ +#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ -#ifdef CONFIG_EXFAT_DEBUG_MSG +#ifdef CONFIG_STAGING_EXFAT_DEBUG_MSG #define DEBUG 1 #else #undef DEBUG @@ -661,10 +661,10 @@ struct exfat_mount_options { /* on error: continue, panic, remount-ro */ unsigned char errors; -#ifdef CONFIG_EXFAT_DISCARD +#ifdef CONFIG_STAGING_EXFAT_DISCARD /* flag on if -o dicard specified and device support discard() */ unsigned char discard; -#endif /* CONFIG_EXFAT_DISCARD */ +#endif /* CONFIG_STAGING_EXFAT_DISCARD */ }; #define EXFAT_HASH_BITS 8 @@ -700,9 +700,9 @@ struct exfat_sb_info { spinlock_t inode_hash_lock; struct hlist_head inode_hashtable[EXFAT_HASH_SIZE]; -#ifdef CONFIG_EXFAT_KERNEL_DEBUG +#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG long debug_flags; -#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ +#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ }; /* diff --git a/drivers/staging/exfat/exfat_blkdev.c b/drivers/staging/exfat/exfat_blkdev.c index 7bcd98b13109..8791a5f2bb08 100644 --- a/drivers/staging/exfat/exfat_blkdev.c +++ b/drivers/staging/exfat/exfat_blkdev.c @@ -35,13 +35,13 @@ int exfat_bdev_read(struct super_block *sb, sector_t secno, struct buffer_head * { struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); -#ifdef CONFIG_EXFAT_KERNEL_DEBUG +#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG struct exfat_sb_info *sbi = EXFAT_SB(sb); long flags = sbi->debug_flags; if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return -EIO; -#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ +#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ if (!p_bd->opened) return -ENODEV; @@ -72,13 +72,13 @@ int exfat_bdev_write(struct super_block *sb, sector_t secno, struct buffer_head struct buffer_head *bh2; struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); -#ifdef CONFIG_EXFAT_KERNEL_DEBUG +#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG struct exfat_sb_info *sbi = EXFAT_SB(sb); long flags = sbi->debug_flags; if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return -EIO; -#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ +#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ if (!p_bd->opened) return -ENODEV; @@ -121,13 +121,13 @@ no_bh: int exfat_bdev_sync(struct super_block *sb) { struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); -#ifdef CONFIG_EXFAT_KERNEL_DEBUG +#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG struct exfat_sb_info *sbi = EXFAT_SB(sb); long flags = sbi->debug_flags; if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return -EIO; -#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ +#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ if (!p_bd->opened) return -ENODEV; diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c index 794000e7bc6f..5e7645fe8c45 100644 --- a/drivers/staging/exfat/exfat_core.c +++ b/drivers/staging/exfat/exfat_core.c @@ -177,11 +177,11 @@ static s32 clr_alloc_bitmap(struct super_block *sb, u32 clu) { int i, b; sector_t sector; -#ifdef CONFIG_EXFAT_DISCARD +#ifdef CONFIG_STAGING_EXFAT_DISCARD struct exfat_sb_info *sbi = EXFAT_SB(sb); struct exfat_mount_options *opts = &sbi->options; int ret; -#endif /* CONFIG_EXFAT_DISCARD */ +#endif /* CONFIG_STAGING_EXFAT_DISCARD */ struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); @@ -192,7 +192,7 @@ static s32 clr_alloc_bitmap(struct super_block *sb, u32 clu) exfat_bitmap_clear((u8 *)p_fs->vol_amap[i]->b_data, b); -#ifdef CONFIG_EXFAT_DISCARD +#ifdef CONFIG_STAGING_EXFAT_DISCARD if (opts->discard) { ret = sb_issue_discard(sb, START_SECTOR(clu), (1 << p_fs->sectors_per_clu_bits), @@ -204,7 +204,7 @@ static s32 clr_alloc_bitmap(struct super_block *sb, u32 clu) return ret; } } -#endif /* CONFIG_EXFAT_DISCARD */ +#endif /* CONFIG_STAGING_EXFAT_DISCARD */ return sector_write(sb, sector, p_fs->vol_amap[i], 0); } diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 744344a2521c..9fa2ad3627c5 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -38,8 +38,8 @@ static struct kmem_cache *exfat_inode_cachep; -static int exfat_default_codepage = CONFIG_EXFAT_DEFAULT_CODEPAGE; -static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET; +static int exfat_default_codepage = CONFIG_STAGING_EXFAT_DEFAULT_CODEPAGE; +static char exfat_default_iocharset[] = CONFIG_STAGING_EXFAT_DEFAULT_IOCHARSET; #define INC_IVERSION(x) (inode_inc_iversion(x)) #define GET_IVERSION(x) (inode_peek_iversion_raw(x)) @@ -647,7 +647,7 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode, /* create a new file */ ret = create_file(inode, &dir, &uni_name, mode, fid); -#ifndef CONFIG_EXFAT_DELAYED_SYNC +#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif @@ -1008,7 +1008,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, update_dir_checksum_with_entry_set(sb, es); release_entry_set(es); -#ifndef CONFIG_EXFAT_DELAYED_SYNC +#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif @@ -1134,7 +1134,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) if (fid->rwoffset > fid->size) fid->rwoffset = fid->size; -#ifndef CONFIG_EXFAT_DELAYED_SYNC +#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif @@ -1282,7 +1282,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, num_entries + 1); } out: -#ifndef CONFIG_EXFAT_DELAYED_SYNC +#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif @@ -1344,7 +1344,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid) fid->start_clu = CLUSTER_32(~0); fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; -#ifndef CONFIG_EXFAT_DELAYED_SYNC +#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif @@ -1420,7 +1420,7 @@ static int ffsSetAttr(struct inode *inode, u32 attr) update_dir_checksum_with_entry_set(sb, es); release_entry_set(es); -#ifndef CONFIG_EXFAT_DELAYED_SYNC +#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif @@ -1804,7 +1804,7 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid) ret = create_dir(inode, &dir, &uni_name, fid); -#ifndef CONFIG_EXFAT_DELAYED_SYNC +#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif @@ -2053,7 +2053,7 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid) fid->start_clu = CLUSTER_32(~0); fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; -#ifndef CONFIG_EXFAT_DELAYED_SYNC +#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif @@ -2176,14 +2176,14 @@ static long exfat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct inode *inode = filp->f_path.dentry->d_inode; -#ifdef CONFIG_EXFAT_KERNEL_DEBUG +#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG unsigned int flags; -#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ +#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ switch (cmd) { case EXFAT_IOCTL_GET_VOLUME_ID: return exfat_ioctl_volume_id(inode); -#ifdef CONFIG_EXFAT_KERNEL_DEBUG +#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG case EXFAT_IOC_GET_DEBUGFLAGS: { struct super_block *sb = inode->i_sb; struct exfat_sb_info *sbi = EXFAT_SB(sb); @@ -2207,7 +2207,7 @@ static long exfat_generic_ioctl(struct file *filp, unsigned int cmd, return 0; } -#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ +#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ default: return -ENOTTY; /* Inappropriate ioctl for device */ } @@ -3400,7 +3400,7 @@ static int exfat_show_options(struct seq_file *m, struct dentry *root) seq_puts(m, ",errors=panic"); else seq_puts(m, ",errors=remount-ro"); -#ifdef CONFIG_EXFAT_DISCARD +#ifdef CONFIG_STAGING_EXFAT_DISCARD if (opts->discard) seq_puts(m, ",discard"); #endif @@ -3481,7 +3481,7 @@ enum { Opt_err_ro, Opt_utf8_hack, Opt_err, -#ifdef CONFIG_EXFAT_DISCARD +#ifdef CONFIG_STAGING_EXFAT_DISCARD Opt_discard, #endif /* EXFAT_CONFIG_DISCARD */ }; @@ -3501,9 +3501,9 @@ static const match_table_t exfat_tokens = { {Opt_err_panic, "errors=panic"}, {Opt_err_ro, "errors=remount-ro"}, {Opt_utf8_hack, "utf8"}, -#ifdef CONFIG_EXFAT_DISCARD +#ifdef CONFIG_STAGING_EXFAT_DISCARD {Opt_discard, "discard"}, -#endif /* CONFIG_EXFAT_DISCARD */ +#endif /* CONFIG_STAGING_EXFAT_DISCARD */ {Opt_err, NULL} }; @@ -3524,7 +3524,7 @@ static int parse_options(char *options, int silent, int *debug, opts->iocharset = exfat_default_iocharset; opts->casesensitive = 0; opts->errors = EXFAT_ERRORS_RO; -#ifdef CONFIG_EXFAT_DISCARD +#ifdef CONFIG_STAGING_EXFAT_DISCARD opts->discard = 0; #endif *debug = 0; @@ -3595,11 +3595,11 @@ static int parse_options(char *options, int silent, int *debug, case Opt_debug: *debug = 1; break; -#ifdef CONFIG_EXFAT_DISCARD +#ifdef CONFIG_STAGING_EXFAT_DISCARD case Opt_discard: opts->discard = 1; break; -#endif /* CONFIG_EXFAT_DISCARD */ +#endif /* CONFIG_STAGING_EXFAT_DISCARD */ case Opt_utf8_hack: break; default: @@ -3803,7 +3803,7 @@ static void __exit exfat_destroy_inodecache(void) kmem_cache_destroy(exfat_inode_cachep); } -#ifdef CONFIG_EXFAT_KERNEL_DEBUG +#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG static void exfat_debug_kill_sb(struct super_block *sb) { struct exfat_sb_info *sbi = EXFAT_SB(sb); @@ -3831,17 +3831,17 @@ static void exfat_debug_kill_sb(struct super_block *sb) kill_block_super(sb); } -#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ +#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ static struct file_system_type exfat_fs_type = { .owner = THIS_MODULE, .name = "exfat", .mount = exfat_fs_mount, -#ifdef CONFIG_EXFAT_KERNEL_DEBUG +#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG .kill_sb = exfat_debug_kill_sb, #else .kill_sb = kill_block_super, -#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ +#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */ .fs_flags = FS_REQUIRES_DEV, }; From 0469fc6a1a8715b5c09117a26700da0d67061fb5 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 21 Dec 2019 00:15:43 +0000 Subject: [PATCH 199/353] staging: wfx: check for memory allocation failures from wfx_alloc_hif Currently calls to wfx_alloc_hif are not checking for a null return when a memory allocation fails and this leads to null pointer dereferencing issues. Fix this by adding null pointer checks and returning passing down -ENOMEM errors where necessary. The error checking in the current driver is a bit sparse, so this may need some extra attention later if required. Fixes: f95a29d40782 ("staging: wfx: add HIF commands helpers") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20191221001543.15255-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx.c | 6 ++++++ drivers/staging/wfx/sta.c | 13 +++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index 8a34a52dd5b9..d8e159670eae 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -366,6 +366,9 @@ int hif_set_edca_queue_params(struct wfx_vif *wvif, u16 queue, struct hif_req_edca_queue_params *body = wfx_alloc_hif(sizeof(*body), &hif); + if (!body) + return -ENOMEM; + WARN_ON(arg->aifs > 255); body->aifsn = arg->aifs; body->cw_min = cpu_to_le16(arg->cw_min); @@ -390,6 +393,9 @@ int hif_set_pm(struct wfx_vif *wvif, bool ps, int dynamic_ps_timeout) struct hif_msg *hif; struct hif_req_set_pm_mode *body = wfx_alloc_hif(sizeof(*body), &hif); + if (!body) + return -ENOMEM; + if (ps) { body->pm_mode.enter_psm = 1; // Firmware does not support more than 128ms diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 9a61478d98f8..9011b5d78706 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -316,6 +316,7 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; + int ret = 0; WARN_ON(queue >= hw->queues); @@ -326,10 +327,10 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (wvif->vif->type == NL80211_IFTYPE_STATION) { hif_set_uapsd_info(wvif, wvif->uapsd_mask); if (wvif->setbssparams_done && wvif->state == WFX_STATE_STA) - wfx_update_pm(wvif); + ret = wfx_update_pm(wvif); } mutex_unlock(&wdev->conf_mutex); - return 0; + return ret; } int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) @@ -1322,7 +1323,7 @@ int wfx_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_PS) { wvif = NULL; while ((wvif = wvif_iterate(wdev, wvif)) != NULL) - wfx_update_pm(wvif); + ret = wfx_update_pm(wvif); wvif = wdev_to_wvif(wdev, 0); } @@ -1333,7 +1334,7 @@ int wfx_config(struct ieee80211_hw *hw, u32 changed) int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - int i; + int i, ret = 0; struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; @@ -1417,9 +1418,9 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) else hif_set_block_ack_policy(wvif, 0x00, 0x00); // Combo force powersave mode. We can re-enable it now - wfx_update_pm(wvif); + ret = wfx_update_pm(wvif); } - return 0; + return ret; } void wfx_remove_interface(struct ieee80211_hw *hw, From 47f6e54c53c5235137ffef50aeaa2c899b3a2ad8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 5 Jan 2020 01:37:10 +0900 Subject: [PATCH 200/353] staging: rts5208: remove unneeded header include path A header include path without $(srctree)/ is suspicous because it does not work with O= builds. I can build drivers/staging/rts5208/ without this include path. Signed-off-by: Masahiro Yamada Link: https://lore.kernel.org/r/20200104163710.21582-1-masahiroy@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/rts5208/Makefile b/drivers/staging/rts5208/Makefile index 6a934c41c738..3c9e9797d3d9 100644 --- a/drivers/staging/rts5208/Makefile +++ b/drivers/staging/rts5208/Makefile @@ -1,7 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_RTS5208) := rts5208.o -ccflags-y := -Idrivers/scsi - rts5208-y := rtsx.o rtsx_chip.o rtsx_transport.o rtsx_scsi.o \ rtsx_card.o general.o sd.o xd.o ms.o spi.o From c497ae2077c055b85c1bf04f3d182a84bd8f365b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 4 Jan 2020 22:48:21 +0100 Subject: [PATCH 201/353] staging: rtl8188: avoid excessive stack usage The rtl8188 copy of the os_dep support code causes a warning about a very significant stack usage in the translate_scan() function: drivers/staging/rtl8188eu/os_dep/ioctl_linux.c: In function 'translate_scan': drivers/staging/rtl8188eu/os_dep/ioctl_linux.c:306:1: error: the frame size of 1560 bytes is larger than 1400 bytes [-Werror=frame-larger-than=] Use the same trick as in the rtl8723bs copy of the same function, and allocate it dynamically. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20200104214832.558198-1-arnd@arndb.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index 710c33fd4965..47f4cc6a19a9 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -222,18 +222,21 @@ static char *translate_scan(struct adapter *padapter, /* parsing WPA/WPA2 IE */ { - u8 buf[MAX_WPA_IE_LEN]; + u8 *buf; u8 wpa_ie[255], rsn_ie[255]; u16 wpa_len = 0, rsn_len = 0; u8 *p; + buf = kzalloc(MAX_WPA_IE_LEN, GFP_ATOMIC); + if (!buf) + return start; + 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: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len)); if (wpa_len > 0) { p = buf; - memset(buf, 0, MAX_WPA_IE_LEN); p += sprintf(p, "wpa_ie="); for (i = 0; i < wpa_len; i++) p += sprintf(p, "%02x", wpa_ie[i]); @@ -250,7 +253,6 @@ static char *translate_scan(struct adapter *padapter, } if (rsn_len > 0) { p = buf; - memset(buf, 0, MAX_WPA_IE_LEN); p += sprintf(p, "rsn_ie="); for (i = 0; i < rsn_len; i++) p += sprintf(p, "%02x", rsn_ie[i]); @@ -264,6 +266,7 @@ static char *translate_scan(struct adapter *padapter, iwe.u.data.length = rsn_len; start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie); } + kfree(buf); } {/* parsing WPS IE */ From 0c5e99c920a7812411dba26667edeac5d21f8836 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sun, 5 Jan 2020 20:49:35 +0100 Subject: [PATCH 202/353] staging: rtl8188eu: remove else after return Remove else after return in rtl88eu_dm_antenna_diversity() to improve readability and clear a checkpatch warning. WARNING: else is not generally useful after a break or return Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200105194936.5477-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/odm_rtl8188e.c | 26 +++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c b/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c index 251bd8aba3b1..7bfba7692ab8 100644 --- a/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c +++ b/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c @@ -303,6 +303,7 @@ void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm) if (!(dm_odm->SupportAbility & ODM_BB_ANT_DIV)) return; + if (!dm_odm->bLinked) { ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_AntennaDiversity_88E(): No Link.\n")); @@ -318,19 +319,20 @@ void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm) dm_fat_tbl->bBecomeLinked = dm_odm->bLinked; } return; - } else { - if (!dm_fat_tbl->bBecomeLinked) { - ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, - ("Need to Turn on HW AntDiv\n")); - phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 1); - phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N, - BIT(15), 1); - if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) - phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N, - BIT(21), 1); - dm_fat_tbl->bBecomeLinked = dm_odm->bLinked; - } } + + if (!dm_fat_tbl->bBecomeLinked) { + ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, + ("Need to Turn on HW AntDiv\n")); + phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 1); + phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N, + BIT(15), 1); + if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) + phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N, + BIT(21), 1); + dm_fat_tbl->bBecomeLinked = dm_odm->bLinked; + } + if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) || (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)) rtl88eu_dm_hw_ant_div(dm_odm); From b4cf24cc936b1552261d7bc5557aa1d8007e5be8 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sun, 5 Jan 2020 20:49:36 +0100 Subject: [PATCH 203/353] staging: rtl8188eu: refactor rtl88eu_dm_update_rx_idle_ant() Refactor rtl88eu_dm_update_rx_idle_ant() to reduce indentation level and clear line over 80 characters checkpatch warnings. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200105194936.5477-2-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/odm_rtl8188e.c | 56 ++++++++++---------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c b/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c index 7bfba7692ab8..a55a0d8b9fb7 100644 --- a/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c +++ b/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c @@ -154,35 +154,37 @@ void rtl88eu_dm_update_rx_idle_ant(struct odm_dm_struct *dm_odm, u8 ant) struct adapter *adapter = dm_odm->Adapter; u32 default_ant, optional_ant; - if (dm_fat_tbl->RxIdleAnt != ant) { - if (ant == MAIN_ANT) { - default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? - MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; - optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? - AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; - } else { - default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? - AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; - optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? - MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; - } + if (dm_fat_tbl->RxIdleAnt == ant) + return; - if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) { - phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, - BIT(5) | BIT(4) | BIT(3), default_ant); - phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, - BIT(8) | BIT(7) | BIT(6), optional_ant); - phy_set_bb_reg(adapter, ODM_REG_ANTSEL_CTRL_11N, - BIT(14) | BIT(13) | BIT(12), default_ant); - phy_set_bb_reg(adapter, ODM_REG_RESP_TX_11N, - BIT(6) | BIT(7), default_ant); - } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) { - phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, - BIT(5) | BIT(4) | BIT(3), default_ant); - phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, - BIT(8) | BIT(7) | BIT(6), optional_ant); - } + if (ant == MAIN_ANT) { + default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? + MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; + optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? + AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; + } else { + default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? + AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; + optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ? + MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; } + + if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) { + phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, + BIT(5) | BIT(4) | BIT(3), default_ant); + phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, + BIT(8) | BIT(7) | BIT(6), optional_ant); + phy_set_bb_reg(adapter, ODM_REG_ANTSEL_CTRL_11N, + BIT(14) | BIT(13) | BIT(12), default_ant); + phy_set_bb_reg(adapter, ODM_REG_RESP_TX_11N, + BIT(6) | BIT(7), default_ant); + } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) { + phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, + BIT(5) | BIT(4) | BIT(3), default_ant); + phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, + BIT(8) | BIT(7) | BIT(6), optional_ant); + } + dm_fat_tbl->RxIdleAnt = ant; } From 9033db57a59a7cd86abe9463f040b60aee51ccf2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 5 Jan 2020 01:21:34 +0900 Subject: [PATCH 204/353] staging: rtl8192u: remove unused Makefile drivers/staging/rtl8192u/ieee80211/Makefile is not used at all. All the build rules are described in drivers/staging/rtl8192u/Makefile. Signed-off-by: Masahiro Yamada Link: https://lore.kernel.org/r/20200104162136.19170-1-masahiroy@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/Makefile | 27 --------------------- 1 file changed, 27 deletions(-) delete mode 100644 drivers/staging/rtl8192u/ieee80211/Makefile diff --git a/drivers/staging/rtl8192u/ieee80211/Makefile b/drivers/staging/rtl8192u/ieee80211/Makefile deleted file mode 100644 index 0d4d6489f767..000000000000 --- a/drivers/staging/rtl8192u/ieee80211/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -NIC_SELECT = RTL8192U - -ccflags-y := -O2 -ccflags-y += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX - -ieee80211-rsl-objs := ieee80211_rx.o \ - ieee80211_softmac.o \ - ieee80211_tx.o \ - ieee80211_wx.o \ - ieee80211_module.o \ - ieee80211_softmac_wx.o\ - rtl819x_HTProc.o\ - rtl819x_TSProc.o\ - rtl819x_BAProc.o\ - dot11d.o - -ieee80211_crypt-rsl-objs := ieee80211_crypt.o -ieee80211_crypt_tkip-rsl-objs := ieee80211_crypt_tkip.o -ieee80211_crypt_ccmp-rsl-objs := ieee80211_crypt_ccmp.o -ieee80211_crypt_wep-rsl-objs := ieee80211_crypt_wep.o - -obj-m +=ieee80211-rsl.o -obj-m +=ieee80211_crypt-rsl.o -obj-m +=ieee80211_crypt_wep-rsl.o -obj-m +=ieee80211_crypt_tkip-rsl.o -obj-m +=ieee80211_crypt_ccmp-rsl.o From 71fe59536e8a4b649c5d78d3ac58a66c03d34f38 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 5 Jan 2020 01:21:35 +0900 Subject: [PATCH 205/353] staging: rtl8192u: remove header include path to ieee80211/ There is no need to add "ccflags-y += -I $(srctree)/$(src)/ieee80211" just for including "dot11d.h". Use the correct relative path for the #include "..." directive. Signed-off-by: Masahiro Yamada Link: https://lore.kernel.org/r/20200104162136.19170-2-masahiroy@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/Makefile | 1 - drivers/staging/rtl8192u/r8192U_core.c | 2 +- drivers/staging/rtl8192u/r8192U_wx.c | 2 +- drivers/staging/rtl8192u/r819xU_phy.c | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8192u/Makefile b/drivers/staging/rtl8192u/Makefile index dcd51bf4aed3..a7e5d3d91d9c 100644 --- a/drivers/staging/rtl8192u/Makefile +++ b/drivers/staging/rtl8192u/Makefile @@ -7,7 +7,6 @@ ccflags-y += -O2 ccflags-y += -DCONFIG_FORCE_HARD_FLOAT=y ccflags-y += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX ccflags-y += -DTHOMAS_BEACON -DTHOMAS_TASKLET -DTHOMAS_SKB -DTHOMAS_TURBO -ccflags-y += -I $(srctree)/$(src)/ieee80211 r8192u_usb-y := r8192U_core.o r8180_93cx6.o r8192U_wx.o \ r8190_rtl8256.o r819xU_phy.o r819xU_firmware.o \ diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 7e2cabd16e88..00fdcbf64b0b 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -60,7 +60,7 @@ double __extendsfdf2(float a) #include /* FIXME: check if 2.6.7 is ok */ -#include "dot11d.h" +#include "ieee80211/dot11d.h" /* set here to open your trace code. */ u32 rt_global_debug_component = COMP_DOWN | COMP_SEC | diff --git a/drivers/staging/rtl8192u/r8192U_wx.c b/drivers/staging/rtl8192u/r8192U_wx.c index 5822bb7984b9..0118edb0b9ab 100644 --- a/drivers/staging/rtl8192u/r8192U_wx.c +++ b/drivers/staging/rtl8192u/r8192U_wx.c @@ -23,7 +23,7 @@ #include "r8192U.h" #include "r8192U_hw.h" -#include "dot11d.h" +#include "ieee80211/dot11d.h" #include "r8192U_wx.h" #define RATE_COUNT 12 diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c index c04d8eca0cfb..555e52522be6 100644 --- a/drivers/staging/rtl8192u/r819xU_phy.c +++ b/drivers/staging/rtl8192u/r819xU_phy.c @@ -7,7 +7,7 @@ #include "r8192U_dm.h" #include "r819xU_firmware_img.h" -#include "dot11d.h" +#include "ieee80211/dot11d.h" #include static u32 RF_CHANNEL_TABLE_ZEBRA[] = { From cd42570fa91c2831a23849c8fc59417557d0292a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 5 Jan 2020 01:21:36 +0900 Subject: [PATCH 206/353] staging: rtl8192u: remove unneeded compiler flags -std=gnu89 is specified by the top Makefile. Adding it in a driver Makefile is redundant. A driver should avoid specifying the optimization flag. -O2, -O3, or -Os is passed by the top Makefile based on the CONFIG_CC_OPTIMIZE_FOR_* option. Signed-off-by: Masahiro Yamada Link: https://lore.kernel.org/r/20200104162136.19170-3-masahiroy@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/rtl8192u/Makefile b/drivers/staging/rtl8192u/Makefile index a7e5d3d91d9c..0be7426b6ebc 100644 --- a/drivers/staging/rtl8192u/Makefile +++ b/drivers/staging/rtl8192u/Makefile @@ -1,9 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 NIC_SELECT = RTL8192U -ccflags-y := -std=gnu89 -ccflags-y += -O2 - ccflags-y += -DCONFIG_FORCE_HARD_FLOAT=y ccflags-y += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX ccflags-y += -DTHOMAS_BEACON -DTHOMAS_TASKLET -DTHOMAS_SKB -DTHOMAS_TURBO From 02ede9567e016622fa01f32649127352e11ed61d Mon Sep 17 00:00:00 2001 From: Chuanhong Guo Date: Thu, 9 Jan 2020 16:00:03 +0800 Subject: [PATCH 207/353] staging: mt7621-dts: fix register range of memc node in mt7621.dtsi The memc node from mt7621.dtsi has incorrect register resource. Fix it according to the programming guide. Signed-off-by: Weijie Gao Signed-off-by: Chuanhong Guo Link: https://lore.kernel.org/r/20200109080120.362110-1-gch981213@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mt7621-dts/mt7621.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi index a4c08110094b..d89d68ffa7bc 100644 --- a/drivers/staging/mt7621-dts/mt7621.dtsi +++ b/drivers/staging/mt7621-dts/mt7621.dtsi @@ -138,7 +138,7 @@ memc: memc@5000 { compatible = "mtk,mt7621-memc"; - reg = <0x300 0x100>; + reg = <0x5000 0x1000>; }; cpc: cpc@1fbf0000 { From d971fdd3412f8342747778fb59b8803720ed82b1 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 8 Jan 2020 21:40:58 +0000 Subject: [PATCH 208/353] staging: vt6656: correct packet types for CTS protect, mode. It appears that the driver still transmits in CTS protect mode even though it is not enabled in mac80211. That is both packet types PK_TYPE_11GA and PK_TYPE_11GB both use CTS protect. The only difference between them GA does not use B rates. Find if only B rate in GB or GA in protect mode otherwise transmit packets as PK_TYPE_11A. Cc: stable Signed-off-by: Malcolm Priestley Link: https://lore.kernel.org/r/9c1323ff-dbb3-0eaa-43e1-9453f7390dc0@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 2 ++ drivers/staging/vt6656/rxtx.c | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 6074ceda78bf..0a3f98f64916 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -52,6 +52,8 @@ #define RATE_AUTO 12 #define MAX_RATE 12 +#define VNT_B_RATES (BIT(RATE_1M) | BIT(RATE_2M) |\ + BIT(RATE_5M) | BIT(RATE_11M)) /* * device specific diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index f9020a4f7bbf..39b557511b24 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -815,10 +815,14 @@ int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) if (info->band == NL80211_BAND_5GHZ) { pkt_type = PK_TYPE_11A; } else { - if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - pkt_type = PK_TYPE_11GB; - else - pkt_type = PK_TYPE_11GA; + if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + if (priv->basic_rates & VNT_B_RATES) + pkt_type = PK_TYPE_11GB; + else + pkt_type = PK_TYPE_11GA; + } else { + pkt_type = PK_TYPE_11A; + } } } else { pkt_type = PK_TYPE_11B; From d579c43c82f093e63639151625b2139166c730fd Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 8 Jan 2020 21:41:20 +0000 Subject: [PATCH 209/353] staging: vt6656: use NULLFUCTION stack on mac80211 It appears that the drivers does not go into power save correctly the NULL data packets are not being transmitted because it not enabled in mac80211. The driver needs to capture ieee80211_is_nullfunc headers and copy the duration_id to it's own duration data header. Cc: stable Signed-off-by: Malcolm Priestley Link: https://lore.kernel.org/r/610971ae-555b-a6c3-61b3-444a0c1e35b4@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 1 + drivers/staging/vt6656/rxtx.c | 14 +++++--------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 4ac85ecb0921..131100510bb0 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1014,6 +1014,7 @@ vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id) ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS); ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS); ieee80211_hw_set(priv->hw, SUPPORTS_PS); + ieee80211_hw_set(priv->hw, PS_NULLFUNC_STACK); priv->hw->max_signal = 100; diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 39b557511b24..29caba728906 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -278,11 +278,9 @@ static u16 vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context, PK_TYPE_11B, &buf->b); /* Get Duration and TimeStamp */ - if (ieee80211_is_pspoll(hdr->frame_control)) { - __le16 dur = cpu_to_le16(priv->current_aid | BIT(14) | BIT(15)); - - buf->duration_a = dur; - buf->duration_b = dur; + if (ieee80211_is_nullfunc(hdr->frame_control)) { + buf->duration_a = hdr->duration_id; + buf->duration_b = hdr->duration_id; } else { buf->duration_a = vnt_get_duration_le(priv, tx_context->pkt_type, need_ack); @@ -371,10 +369,8 @@ static u16 vnt_rxtx_datahead_ab(struct vnt_usb_send_context *tx_context, tx_context->pkt_type, &buf->ab); /* Get Duration and TimeStampOff */ - if (ieee80211_is_pspoll(hdr->frame_control)) { - __le16 dur = cpu_to_le16(priv->current_aid | BIT(14) | BIT(15)); - - buf->duration = dur; + if (ieee80211_is_nullfunc(hdr->frame_control)) { + buf->duration = hdr->duration_id; } else { buf->duration = vnt_get_duration_le(priv, tx_context->pkt_type, need_ack); From 9dd631fa99dc0a0dfbd191173bf355ba30ea786a Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 8 Jan 2020 21:41:36 +0000 Subject: [PATCH 210/353] staging: vt6656: Fix false Tx excessive retries reporting. The driver reporting IEEE80211_TX_STAT_ACK is not being handled correctly. The driver should only report on TSR_TMO flag is not set indicating no transmission errors and when not IEEE80211_TX_CTL_NO_ACK is being requested. Cc: stable Signed-off-by: Malcolm Priestley Link: https://lore.kernel.org/r/340f1f7f-c310-dca5-476f-abc059b9cd97@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/int.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/vt6656/int.c b/drivers/staging/vt6656/int.c index f40947955675..af215860be4c 100644 --- a/drivers/staging/vt6656/int.c +++ b/drivers/staging/vt6656/int.c @@ -99,9 +99,11 @@ static int vnt_int_report_rate(struct vnt_private *priv, u8 pkt_no, u8 tsr) info->status.rates[0].count = tx_retry; - if (!(tsr & (TSR_TMO | TSR_RETRYTMO))) { + if (!(tsr & TSR_TMO)) { info->status.rates[0].idx = idx; - info->flags |= IEEE80211_TX_STAT_ACK; + + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) + info->flags |= IEEE80211_TX_STAT_ACK; } ieee80211_tx_status_irqsafe(priv->hw, context->skb); From ab5caf34f5413daa1d58bb827fbb206094e20f0c Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Wed, 8 Jan 2020 21:41:56 +0000 Subject: [PATCH 211/353] staging: vt6656: Move ieee80211_rx_status off stack. ieee80211_rx_status off stack to IEEE80211_SKB_RXCB (skb->cb) removing the need to copy on to it. skb->cb is always present as a clean buffer so simply fill it in. Signed-off-by: Malcolm Priestley Link: https://lore.kernel.org/r/a66caba4-0c17-41af-a58f-3cdbb3243fb0@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/dpc.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 3b94e80f1d5e..2bcb29b11883 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -29,7 +29,7 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, struct ieee80211_hw *hw = priv->hw; struct ieee80211_supported_band *sband; struct sk_buff *skb; - struct ieee80211_rx_status rx_status = { 0 }; + struct ieee80211_rx_status *rx_status; struct ieee80211_hdr *hdr; __le16 fc; u8 *rsr, *new_rsr, *rssi; @@ -46,6 +46,7 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, long rx_dbm; skb = ptr_rcb->skb; + rx_status = IEEE80211_SKB_RXCB(skb); /* [31:16]RcvByteCount ( not include 4-byte Status ) */ wbk_status = *((u32 *)(skb->data)); @@ -136,23 +137,23 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, skb_pull(skb, 8); skb_trim(skb, frame_size); - rx_status.mactime = priv->tsf_time; - rx_status.band = hw->conf.chandef.chan->band; - rx_status.signal = rx_dbm; - rx_status.flag = 0; - rx_status.freq = hw->conf.chandef.chan->center_freq; + rx_status->mactime = priv->tsf_time; + rx_status->band = hw->conf.chandef.chan->band; + rx_status->signal = rx_dbm; + rx_status->flag = 0; + rx_status->freq = hw->conf.chandef.chan->center_freq; if (!(*rsr & RSR_CRCOK)) - rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; hdr = (struct ieee80211_hdr *)(skb->data); fc = hdr->frame_control; - rx_status.rate_idx = rate_idx; + rx_status->rate_idx = rate_idx; if (ieee80211_has_protected(fc)) { if (priv->local_id > REV_ID_VT3253_A1) { - rx_status.flag |= RX_FLAG_DECRYPTED; + rx_status->flag |= RX_FLAG_DECRYPTED; /* Drop packet */ if (!(*new_rsr & NEWRSR_DECRYPTOK)) { @@ -162,8 +163,6 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, } } - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - ieee80211_rx_irqsafe(priv->hw, skb); return true; From e895bc1ebb31750f3baa74e074617d3cc5d0cee2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 10 Jan 2020 22:56:15 +0900 Subject: [PATCH 212/353] staging: vc04_services: remove header include path to vc04_services Fix up some relative paths in #include "..." directives, and remove the include path to drivers/staging/vc04_services. Signed-off-by: Masahiro Yamada Link: https://lore.kernel.org/r/20200110135615.11617-1-masahiroy@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/Makefile | 2 +- drivers/staging/vc04_services/interface/vchi/vchi.h | 4 ++-- .../staging/vc04_services/interface/vchiq_arm/vchiq_shim.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/vc04_services/Makefile b/drivers/staging/vc04_services/Makefile index afe43fa5a6d7..54d9e2f31916 100644 --- a/drivers/staging/vc04_services/Makefile +++ b/drivers/staging/vc04_services/Makefile @@ -13,5 +13,5 @@ vchiq-objs := \ obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/ obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/ -ccflags-y += -Idrivers/staging/vc04_services -D__VCCOREVER__=0x04000000 +ccflags-y += -D__VCCOREVER__=0x04000000 diff --git a/drivers/staging/vc04_services/interface/vchi/vchi.h b/drivers/staging/vc04_services/interface/vchi/vchi.h index 56b1037d8e25..ff2b960d8cac 100644 --- a/drivers/staging/vc04_services/interface/vchi/vchi.h +++ b/drivers/staging/vc04_services/interface/vchi/vchi.h @@ -4,8 +4,8 @@ #ifndef VCHI_H_ #define VCHI_H_ -#include "interface/vchi/vchi_cfg.h" -#include "interface/vchi/vchi_common.h" +#include "vchi_cfg.h" +#include "vchi_common.h" /****************************************************************************** * Global defs diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c index 0ce3b08b3441..efdd3b1c7d85 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c @@ -3,7 +3,7 @@ #include #include -#include "interface/vchi/vchi.h" +#include "../vchi/vchi.h" #include "vchiq.h" #include "vchiq_core.h" From a9ab624edd9186fbad734cfe5d606a6da3ca34db Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 7 Jan 2020 13:45:32 +0200 Subject: [PATCH 213/353] iio: adc: stm32-dfsdm: Use dma_request_chan() instead dma_request_slave_channel() dma_request_slave_channel() is a wrapper on top of dma_request_chan() eating up the error code. By using dma_request_chan() directly the driver can support deferred probing against DMA. Signed-off-by: Peter Ujfalusi Acked-by: Olivier Moysan Acked-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-dfsdm-adc.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index e493242c266e..74a2211bdff4 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -1383,9 +1383,13 @@ static int stm32_dfsdm_dma_request(struct iio_dev *indio_dev) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); - adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx"); - if (!adc->dma_chan) - return -EINVAL; + adc->dma_chan = dma_request_chan(&indio_dev->dev, "rx"); + if (IS_ERR(adc->dma_chan)) { + int ret = PTR_ERR(adc->dma_chan); + + adc->dma_chan = NULL; + return ret; + } adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev, DFSDM_DMA_BUFFER_SIZE, @@ -1509,7 +1513,16 @@ static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev) init_completion(&adc->completion); /* Optionally request DMA */ - if (stm32_dfsdm_dma_request(indio_dev)) { + ret = stm32_dfsdm_dma_request(indio_dev); + if (ret) { + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(&indio_dev->dev, + "DMA channel request failed with %d\n", + ret); + return ret; + } + dev_dbg(&indio_dev->dev, "No DMA support\n"); return 0; } From 735404b846dffcb320264f62b76e6f70012214dd Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 8 Jan 2020 10:08:01 +0200 Subject: [PATCH 214/353] iio: adc: stm32-adc: Use dma_request_chan() instead dma_request_slave_channel() dma_request_slave_channel() is a wrapper on top of dma_request_chan() eating up the error code. By using dma_request_chan() directly the driver can support deferred probing against DMA. Signed-off-by: Peter Ujfalusi Acked-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-adc.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 5f05bf9f16ea..80c3f963527b 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -1796,9 +1796,21 @@ static int stm32_adc_dma_request(struct iio_dev *indio_dev) struct dma_slave_config config; int ret; - adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx"); - if (!adc->dma_chan) + adc->dma_chan = dma_request_chan(&indio_dev->dev, "rx"); + if (IS_ERR(adc->dma_chan)) { + ret = PTR_ERR(adc->dma_chan); + if (ret != -ENODEV) { + if (ret != -EPROBE_DEFER) + dev_err(&indio_dev->dev, + "DMA channel request failed with %d\n", + ret); + return ret; + } + + /* DMA is optional: fall back to IRQ mode */ + adc->dma_chan = NULL; return 0; + } adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev, STM32_DMA_BUFFER_SIZE, From 687d39d4512aa5f644450d0662f40aeeac1e84a7 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 7 Jan 2020 13:37:29 +0200 Subject: [PATCH 215/353] iio: adc: at91-sama5d2_adc: Use dma_request_chan() instead dma_request_slave_channel() dma_request_slave_channel() is a wrapper on top of dma_request_chan() eating up the error code. The dma_request_chan() is the standard API to request slave channel, clients should be moved away from the legacy API to allow us to retire them. Signed-off-by: Peter Ujfalusi Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index e1850f3d5cf3..a5c7771227d5 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -1444,10 +1444,10 @@ static void at91_adc_dma_init(struct platform_device *pdev) if (st->dma_st.dma_chan) return; - st->dma_st.dma_chan = dma_request_slave_channel(&pdev->dev, "rx"); - - if (!st->dma_st.dma_chan) { + st->dma_st.dma_chan = dma_request_chan(&pdev->dev, "rx"); + if (IS_ERR(st->dma_st.dma_chan)) { dev_info(&pdev->dev, "can't get DMA channel\n"); + st->dma_st.dma_chan = NULL; goto dma_exit; } From 380b107bbf9449ddea0637cefe65a6cbf7b6ca84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Tue, 7 Jan 2020 13:17:04 +0200 Subject: [PATCH 216/353] iio: adis: Introduce timeouts structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The adis library only allows to define a `startup_delay` which for some devices is enough. However, other devices define different timeouts with significantly different timings which could lead to devices to not wait enough time or to wait a lot more than necessary (which is not efficient). This patch introduces a new timeout struct that must be passed into `adis_init()`. There are mainly, for now, three timeouts used. This is also an introductory patch with the goal of refactoring `adis_initial_startup()`. New driver's (eg: adis16480, adis16460) are replicating code for the device initial setup. With some changes (being this the first one) we can pass this to `adis_initial_startup()`. Signed-off-by: Nuno Sá Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adis16201.c | 7 +++ drivers/iio/accel/adis16209.c | 7 +++ drivers/iio/gyro/adis16136.c | 40 ++++++++++++++++- drivers/iio/gyro/adis16260.c | 7 +++ drivers/iio/imu/adis.c | 18 ++++++-- drivers/iio/imu/adis16400.c | 63 ++++++++++++++++++++++++++- drivers/iio/imu/adis16460.c | 7 +++ drivers/iio/imu/adis16480.c | 58 +++++++++++++++++++++++- drivers/staging/iio/accel/adis16203.c | 7 +++ drivers/staging/iio/accel/adis16240.c | 7 +++ include/linux/iio/imu/adis.h | 13 ++++++ 11 files changed, 227 insertions(+), 7 deletions(-) diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c index c4810c73b2a2..c92d22387b01 100644 --- a/drivers/iio/accel/adis16201.c +++ b/drivers/iio/accel/adis16201.c @@ -233,6 +233,12 @@ static const char * const adis16201_status_error_msgs[] = { [ADIS16201_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V", }; +static const struct adis_timeout adis16201_timeouts = { + .reset_ms = ADIS16201_STARTUP_DELAY_MS, + .sw_reset_ms = ADIS16201_STARTUP_DELAY_MS, + .self_test_ms = ADIS16201_STARTUP_DELAY_MS, +}; + static const struct adis_data adis16201_data = { .read_delay = 20, .msc_ctrl_reg = ADIS16201_MSC_CTRL_REG, @@ -242,6 +248,7 @@ static const struct adis_data adis16201_data = { .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, .startup_delay = ADIS16201_STARTUP_DELAY_MS, + .timeouts = &adis16201_timeouts, .status_error_msgs = adis16201_status_error_msgs, .status_error_mask = BIT(ADIS16201_DIAG_STAT_SPI_FAIL_BIT) | diff --git a/drivers/iio/accel/adis16209.c b/drivers/iio/accel/adis16209.c index 98d77af8a2b0..f5a78fc11919 100644 --- a/drivers/iio/accel/adis16209.c +++ b/drivers/iio/accel/adis16209.c @@ -243,6 +243,12 @@ static const char * const adis16209_status_error_msgs[] = { [ADIS16209_STAT_POWER_LOW_BIT] = "Power supply below 2.975V", }; +static const struct adis_timeout adis16209_timeouts = { + .reset_ms = ADIS16209_STARTUP_DELAY_MS, + .self_test_ms = ADIS16209_STARTUP_DELAY_MS, + .sw_reset_ms = ADIS16209_STARTUP_DELAY_MS, +}; + static const struct adis_data adis16209_data = { .read_delay = 30, .msc_ctrl_reg = ADIS16209_MSC_CTRL_REG, @@ -252,6 +258,7 @@ static const struct adis_data adis16209_data = { .self_test_mask = ADIS16209_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, .startup_delay = ADIS16209_STARTUP_DELAY_MS, + .timeouts = &adis16209_timeouts, .status_error_msgs = adis16209_status_error_msgs, .status_error_mask = BIT(ADIS16209_STAT_SELFTEST_FAIL_BIT) | diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c index f10c4f173898..dc91d8df7697 100644 --- a/drivers/iio/gyro/adis16136.c +++ b/drivers/iio/gyro/adis16136.c @@ -59,6 +59,7 @@ struct adis16136_chip_info { unsigned int precision; unsigned int fullscale; + const struct adis_timeout *timeouts; }; struct adis16136 { @@ -490,30 +491,63 @@ enum adis16136_id { ID_ADIS16137, }; +static const struct adis_timeout adis16133_timeouts = { + .reset_ms = 75, + .sw_reset_ms = 75, + .self_test_ms = 50, +}; + +static const struct adis_timeout adis16136_timeouts = { + .reset_ms = 128, + .sw_reset_ms = 75, + .self_test_ms = 245, +}; + static const struct adis16136_chip_info adis16136_chip_info[] = { [ID_ADIS16133] = { .precision = IIO_DEGREE_TO_RAD(1200), .fullscale = 24000, + .timeouts = &adis16133_timeouts, }, [ID_ADIS16135] = { .precision = IIO_DEGREE_TO_RAD(300), .fullscale = 24000, + .timeouts = &adis16133_timeouts, }, [ID_ADIS16136] = { .precision = IIO_DEGREE_TO_RAD(450), .fullscale = 24623, + .timeouts = &adis16136_timeouts, }, [ID_ADIS16137] = { .precision = IIO_DEGREE_TO_RAD(1000), .fullscale = 24609, + .timeouts = &adis16136_timeouts, }, }; +static struct adis_data *adis16136_adis_data_alloc(struct adis16136 *st, + struct device *dev) +{ + struct adis_data *data; + + data = devm_kmalloc(dev, sizeof(struct adis_data), GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); + + memcpy(data, &adis16136_data, sizeof(*data)); + + data->timeouts = st->chip_info->timeouts; + + return data; +} + static int adis16136_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); struct adis16136 *adis16136; struct iio_dev *indio_dev; + const struct adis_data *adis16136_data; int ret; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis16136)); @@ -532,7 +566,11 @@ static int adis16136_probe(struct spi_device *spi) indio_dev->info = &adis16136_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = adis_init(&adis16136->adis, indio_dev, spi, &adis16136_data); + adis16136_data = adis16136_adis_data_alloc(adis16136, &spi->dev); + if (IS_ERR(adis16136_data)) + return PTR_ERR(adis16136_data); + + ret = adis_init(&adis16136->adis, indio_dev, spi, adis16136_data); if (ret) return ret; diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c index 726a0aa321a8..0e3a66a7726d 100644 --- a/drivers/iio/gyro/adis16260.c +++ b/drivers/iio/gyro/adis16260.c @@ -332,6 +332,12 @@ static const char * const adis1620_status_error_msgs[] = { [ADIS16260_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 4.75", }; +static const struct adis_timeout adis16260_timeouts = { + .reset_ms = ADIS16260_STARTUP_DELAY, + .sw_reset_ms = ADIS16260_STARTUP_DELAY, + .self_test_ms = ADIS16260_STARTUP_DELAY, +}; + static const struct adis_data adis16260_data = { .write_delay = 30, .read_delay = 30, @@ -341,6 +347,7 @@ static const struct adis_data adis16260_data = { .self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST, .startup_delay = ADIS16260_STARTUP_DELAY, + .timeouts = &adis16260_timeouts, .status_error_msgs = adis1620_status_error_msgs, .status_error_mask = BIT(ADIS16260_DIAG_STAT_FLASH_CHK_BIT) | diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 9ba4a7c8e7ad..8f0867495ef5 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -317,19 +317,25 @@ EXPORT_SYMBOL_GPL(__adis_check_status); int __adis_reset(struct adis *adis) { int ret; + const struct adis_timeout *timeouts = adis->data->timeouts; ret = __adis_write_reg_8(adis, adis->data->glob_cmd_reg, ADIS_GLOB_CMD_SW_RESET); - if (ret) + if (ret) { dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret); + return ret; + } - return ret; + msleep(timeouts->sw_reset_ms); + + return 0; } EXPORT_SYMBOL_GPL(__adis_reset); static int adis_self_test(struct adis *adis) { int ret; + const struct adis_timeout *timeouts = adis->data->timeouts; ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, adis->data->self_test_mask); @@ -339,7 +345,7 @@ static int adis_self_test(struct adis *adis) return ret; } - msleep(adis->data->startup_delay); + msleep(timeouts->self_test_ms); ret = __adis_check_status(adis); @@ -368,7 +374,6 @@ int adis_initial_startup(struct adis *adis) if (ret) { dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n"); __adis_reset(adis); - msleep(adis->data->startup_delay); ret = adis_self_test(adis); if (ret) { dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n"); @@ -444,6 +449,11 @@ EXPORT_SYMBOL_GPL(adis_single_conversion); int adis_init(struct adis *adis, struct iio_dev *indio_dev, struct spi_device *spi, const struct adis_data *data) { + if (!data || !data->timeouts) { + dev_err(&spi->dev, "No config data or timeouts not defined!\n"); + return -EINVAL; + } + mutex_init(&adis->state_lock); adis->spi = spi; adis->data = data; diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 662cb5367c11..51b1ec23b8ef 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -156,6 +156,7 @@ struct adis16400_state; struct adis16400_chip_info { const struct iio_chan_spec *channels; + const struct adis_timeout *timeouts; const int num_channels; const long flags; unsigned int gyro_scale_micro; @@ -929,6 +930,36 @@ static const struct iio_chan_spec adis16334_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), }; +static const struct adis_timeout adis16300_timeouts = { + .reset_ms = ADIS16400_STARTUP_DELAY, + .sw_reset_ms = ADIS16400_STARTUP_DELAY, + .self_test_ms = ADIS16400_STARTUP_DELAY, +}; + +static const struct adis_timeout adis16362_timeouts = { + .reset_ms = 130, + .sw_reset_ms = 130, + .self_test_ms = 12, +}; + +static const struct adis_timeout adis16400_timeouts = { + .reset_ms = 170, + .sw_reset_ms = 170, + .self_test_ms = 12, +}; + +static const struct adis_timeout adis16445_timeouts = { + .reset_ms = 55, + .sw_reset_ms = 55, + .self_test_ms = 16, +}; + +static const struct adis_timeout adis16448_timeouts = { + .reset_ms = 90, + .sw_reset_ms = 90, + .self_test_ms = 45, +}; + static struct adis16400_chip_info adis16400_chips[] = { [ADIS16300] = { .channels = adis16300_channels, @@ -941,6 +972,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16300_timeouts, }, [ADIS16334] = { .channels = adis16334_channels, @@ -964,6 +996,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE, .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16300_timeouts, }, [ADIS16360] = { .channels = adis16350_channels, @@ -976,6 +1009,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16300_timeouts, }, [ADIS16362] = { .channels = adis16350_channels, @@ -988,6 +1022,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16362_timeouts, }, [ADIS16364] = { .channels = adis16350_channels, @@ -1000,6 +1035,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16362_timeouts, }, [ADIS16367] = { .channels = adis16350_channels, @@ -1012,6 +1048,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16300_timeouts, }, [ADIS16400] = { .channels = adis16400_channels, @@ -1023,6 +1060,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, + .timeouts = &adis16400_timeouts, }, [ADIS16445] = { .channels = adis16445_channels, @@ -1036,6 +1074,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ .set_freq = adis16334_set_freq, .get_freq = adis16334_get_freq, + .timeouts = &adis16445_timeouts, }, [ADIS16448] = { .channels = adis16448_channels, @@ -1049,6 +1088,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ .set_freq = adis16334_set_freq, .get_freq = adis16334_get_freq, + .timeouts = &adis16448_timeouts, } }; @@ -1120,11 +1160,28 @@ static void adis16400_setup_chan_mask(struct adis16400_state *st) } } +static struct adis_data *adis16400_adis_data_alloc(struct adis16400_state *st, + struct device *dev) +{ + struct adis_data *data; + + data = devm_kmalloc(dev, sizeof(struct adis_data), GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); + + memcpy(data, &adis16400_data, sizeof(*data)); + + data->timeouts = st->variant->timeouts; + + return data; +} + static int adis16400_probe(struct spi_device *spi) { struct adis16400_state *st; struct iio_dev *indio_dev; int ret; + const struct adis_data *adis16400_data; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (indio_dev == NULL) @@ -1151,7 +1208,11 @@ static int adis16400_probe(struct spi_device *spi) st->adis.burst->extra_len = sizeof(u16); } - ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data); + adis16400_data = adis16400_adis_data_alloc(st, &spi->dev); + if (IS_ERR(adis16400_data)) + return PTR_ERR(adis16400_data); + + ret = adis_init(&st->adis, indio_dev, spi, adis16400_data); if (ret) return ret; diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c index b55812521537..9539cfe4a259 100644 --- a/drivers/iio/imu/adis16460.c +++ b/drivers/iio/imu/adis16460.c @@ -383,6 +383,12 @@ static const char * const adis16460_status_error_msgs[] = { [ADIS16460_DIAG_STAT_FLASH_UPT] = "Flash update failure", }; +static const struct adis_timeout adis16460_timeouts = { + .reset_ms = 225, + .sw_reset_ms = 225, + .self_test_ms = 10, +}; + static const struct adis_data adis16460_data = { .diag_stat_reg = ADIS16460_REG_DIAG_STAT, .glob_cmd_reg = ADIS16460_REG_GLOB_CMD, @@ -398,6 +404,7 @@ static const struct adis_data adis16460_data = { BIT(ADIS16460_DIAG_STAT_SPI_COMM) | BIT(ADIS16460_DIAG_STAT_FLASH_UPT), .enable_irq = adis16460_enable_irq, + .timeouts = &adis16460_timeouts, }; static int adis16460_probe(struct spi_device *spi) diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index f73094e8d35d..f0ad7ce64861 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -138,6 +138,7 @@ struct adis16480_chip_info { unsigned int max_dec_rate; const unsigned int *filter_freqs; bool has_pps_clk_mode; + const struct adis_timeout *timeouts; }; enum adis16480_int_pin { @@ -794,6 +795,30 @@ enum adis16480_variant { ADIS16497_3, }; +static const struct adis_timeout adis16485_timeouts = { + .reset_ms = 560, + .sw_reset_ms = 120, + .self_test_ms = 12, +}; + +static const struct adis_timeout adis16480_timeouts = { + .reset_ms = 560, + .sw_reset_ms = 560, + .self_test_ms = 12, +}; + +static const struct adis_timeout adis16495_timeouts = { + .reset_ms = 170, + .sw_reset_ms = 130, + .self_test_ms = 40, +}; + +static const struct adis_timeout adis16495_1_timeouts = { + .reset_ms = 250, + .sw_reset_ms = 210, + .self_test_ms = 20, +}; + static const struct adis16480_chip_info adis16480_chip_info[] = { [ADIS16375] = { .channels = adis16485_channels, @@ -812,6 +837,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, + .timeouts = &adis16485_timeouts, }, [ADIS16480] = { .channels = adis16480_channels, @@ -824,6 +850,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, + .timeouts = &adis16480_timeouts, }, [ADIS16485] = { .channels = adis16485_channels, @@ -836,6 +863,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, + .timeouts = &adis16485_timeouts, }, [ADIS16488] = { .channels = adis16480_channels, @@ -848,6 +876,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, + .timeouts = &adis16485_timeouts, }, [ADIS16495_1] = { .channels = adis16485_channels, @@ -861,6 +890,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, + .timeouts = &adis16495_1_timeouts, }, [ADIS16495_2] = { .channels = adis16485_channels, @@ -874,6 +904,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, + .timeouts = &adis16495_1_timeouts, }, [ADIS16495_3] = { .channels = adis16485_channels, @@ -887,6 +918,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, + .timeouts = &adis16495_1_timeouts, }, [ADIS16497_1] = { .channels = adis16485_channels, @@ -900,6 +932,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, + .timeouts = &adis16495_1_timeouts, }, [ADIS16497_2] = { .channels = adis16485_channels, @@ -913,6 +946,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, + .timeouts = &adis16495_1_timeouts, }, [ADIS16497_3] = { .channels = adis16485_channels, @@ -926,6 +960,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, + .timeouts = &adis16495_1_timeouts, }, }; @@ -1195,9 +1230,26 @@ static int adis16480_get_ext_clocks(struct adis16480 *st) return 0; } +static struct adis_data *adis16480_adis_data_alloc(struct adis16480 *st, + struct device *dev) +{ + struct adis_data *data; + + data = devm_kmalloc(dev, sizeof(struct adis_data), GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); + + memcpy(data, &adis16480_data, sizeof(*data)); + + data->timeouts = st->chip_info->timeouts; + + return data; +} + static int adis16480_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); + const struct adis_data *adis16480_data; struct iio_dev *indio_dev; struct adis16480 *st; int ret; @@ -1218,7 +1270,11 @@ static int adis16480_probe(struct spi_device *spi) indio_dev->info = &adis16480_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = adis_init(&st->adis, indio_dev, spi, &adis16480_data); + adis16480_data = adis16480_adis_data_alloc(st, &spi->dev); + if (IS_ERR(adis16480_data)) + return PTR_ERR(adis16480_data); + + ret = adis_init(&st->adis, indio_dev, spi, adis16480_data); if (ret) return ret; diff --git a/drivers/staging/iio/accel/adis16203.c b/drivers/staging/iio/accel/adis16203.c index 39687139a7d3..3d706ee02df0 100644 --- a/drivers/staging/iio/accel/adis16203.c +++ b/drivers/staging/iio/accel/adis16203.c @@ -237,6 +237,12 @@ static const char * const adis16203_status_error_msgs[] = { [ADIS16203_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V", }; +static const struct adis_timeout adis16203_timeouts = { + .reset_ms = ADIS16203_STARTUP_DELAY, + .sw_reset_ms = ADIS16203_STARTUP_DELAY, + .self_test_ms = ADIS16203_STARTUP_DELAY +}; + static const struct adis_data adis16203_data = { .read_delay = 20, .msc_ctrl_reg = ADIS16203_MSC_CTRL, @@ -246,6 +252,7 @@ static const struct adis_data adis16203_data = { .self_test_mask = ADIS16203_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, .startup_delay = ADIS16203_STARTUP_DELAY, + .timeouts = &adis16203_timeouts, .status_error_msgs = adis16203_status_error_msgs, .status_error_mask = BIT(ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT) | diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c index 794f063e6c86..d4848ef78c75 100644 --- a/drivers/staging/iio/accel/adis16240.c +++ b/drivers/staging/iio/accel/adis16240.c @@ -359,6 +359,12 @@ static const char * const adis16240_status_error_msgs[] = { [ADIS16240_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.225V", }; +static const struct adis_timeout adis16240_timeouts = { + .reset_ms = ADIS16240_STARTUP_DELAY, + .sw_reset_ms = ADIS16240_STARTUP_DELAY, + .self_test_ms = ADIS16240_STARTUP_DELAY, +}; + static const struct adis_data adis16240_data = { .write_delay = 35, .read_delay = 35, @@ -369,6 +375,7 @@ static const struct adis_data adis16240_data = { .self_test_mask = ADIS16240_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, .startup_delay = ADIS16240_STARTUP_DELAY, + .timeouts = &adis16240_timeouts, .status_error_msgs = adis16240_status_error_msgs, .status_error_mask = BIT(ADIS16240_DIAG_STAT_PWRON_FAIL_BIT) | diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 4b5bc0e06e69..853dc8c8365c 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -22,6 +22,17 @@ struct adis; struct adis_burst; +/** + * struct adis_timeouts - ADIS chip variant timeouts + * @reset_ms - Wait time after rst pin goes inactive + * @sw_reset_ms - Wait time after sw reset command + * @self_test_ms - Wait time after self test command + */ +struct adis_timeout { + u16 reset_ms; + u16 sw_reset_ms; + u16 self_test_ms; +}; /** * struct adis_data - ADIS chip variant specific data * @read_delay: SPI delay for read operations in us @@ -32,6 +43,7 @@ struct adis_burst; * @diag_stat_reg: Register address of the DIAG_STAT register * @status_error_msgs: Array of error messgaes * @status_error_mask: + * @timeouts: Chip specific delays */ struct adis_data { unsigned int read_delay; @@ -45,6 +57,7 @@ struct adis_data { unsigned int self_test_mask; bool self_test_no_autoclear; unsigned int startup_delay; + const struct adis_timeout *timeouts; const char * const *status_error_msgs; unsigned int status_error_mask; From 77038bd01ce66ae65bcb66266c9747b670b5facd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Tue, 7 Jan 2020 13:17:05 +0200 Subject: [PATCH 217/353] iio: adis: Remove startup_delay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All timeouts are now handled by a dedicated timeout struct. This variable is no longer needed. Signed-off-by: Nuno Sá Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adis16201.c | 1 - drivers/iio/accel/adis16209.c | 1 - drivers/iio/gyro/adis16136.c | 1 - drivers/iio/gyro/adis16260.c | 1 - drivers/iio/imu/adis16400.c | 1 - drivers/staging/iio/accel/adis16203.c | 1 - drivers/staging/iio/accel/adis16240.c | 1 - include/linux/iio/imu/adis.h | 1 - 8 files changed, 8 deletions(-) diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c index c92d22387b01..0f0f27a8184e 100644 --- a/drivers/iio/accel/adis16201.c +++ b/drivers/iio/accel/adis16201.c @@ -247,7 +247,6 @@ static const struct adis_data adis16201_data = { .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, - .startup_delay = ADIS16201_STARTUP_DELAY_MS, .timeouts = &adis16201_timeouts, .status_error_msgs = adis16201_status_error_msgs, diff --git a/drivers/iio/accel/adis16209.c b/drivers/iio/accel/adis16209.c index f5a78fc11919..c6dbd2424e10 100644 --- a/drivers/iio/accel/adis16209.c +++ b/drivers/iio/accel/adis16209.c @@ -257,7 +257,6 @@ static const struct adis_data adis16209_data = { .self_test_mask = ADIS16209_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, - .startup_delay = ADIS16209_STARTUP_DELAY_MS, .timeouts = &adis16209_timeouts, .status_error_msgs = adis16209_status_error_msgs, diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c index dc91d8df7697..d5e03a406d4a 100644 --- a/drivers/iio/gyro/adis16136.c +++ b/drivers/iio/gyro/adis16136.c @@ -472,7 +472,6 @@ static const struct adis_data adis16136_data = { .msc_ctrl_reg = ADIS16136_REG_MSC_CTRL, .self_test_mask = ADIS16136_MSC_CTRL_SELF_TEST, - .startup_delay = 80, .read_delay = 10, .write_delay = 10, diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c index 0e3a66a7726d..be09b3e5910c 100644 --- a/drivers/iio/gyro/adis16260.c +++ b/drivers/iio/gyro/adis16260.c @@ -346,7 +346,6 @@ static const struct adis_data adis16260_data = { .diag_stat_reg = ADIS16260_DIAG_STAT, .self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST, - .startup_delay = ADIS16260_STARTUP_DELAY, .timeouts = &adis16260_timeouts, .status_error_msgs = adis1620_status_error_msgs, diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 51b1ec23b8ef..cfb1c19eb930 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -1126,7 +1126,6 @@ static const struct adis_data adis16400_data = { .write_delay = 50, .self_test_mask = ADIS16400_MSC_CTRL_MEM_TEST, - .startup_delay = ADIS16400_STARTUP_DELAY, .status_error_msgs = adis16400_status_error_msgs, .status_error_mask = BIT(ADIS16400_DIAG_STAT_ZACCL_FAIL) | diff --git a/drivers/staging/iio/accel/adis16203.c b/drivers/staging/iio/accel/adis16203.c index 3d706ee02df0..39dfe3f7f254 100644 --- a/drivers/staging/iio/accel/adis16203.c +++ b/drivers/staging/iio/accel/adis16203.c @@ -251,7 +251,6 @@ static const struct adis_data adis16203_data = { .self_test_mask = ADIS16203_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, - .startup_delay = ADIS16203_STARTUP_DELAY, .timeouts = &adis16203_timeouts, .status_error_msgs = adis16203_status_error_msgs, diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c index d4848ef78c75..39eb8364aa95 100644 --- a/drivers/staging/iio/accel/adis16240.c +++ b/drivers/staging/iio/accel/adis16240.c @@ -374,7 +374,6 @@ static const struct adis_data adis16240_data = { .self_test_mask = ADIS16240_MSC_CTRL_SELF_TEST_EN, .self_test_no_autoclear = true, - .startup_delay = ADIS16240_STARTUP_DELAY, .timeouts = &adis16240_timeouts, .status_error_msgs = adis16240_status_error_msgs, diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 853dc8c8365c..d2fcf45b4cef 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -56,7 +56,6 @@ struct adis_data { unsigned int self_test_mask; bool self_test_no_autoclear; - unsigned int startup_delay; const struct adis_timeout *timeouts; const char * const *status_error_msgs; From f335fa7034d5444de53f22824afce52924d95253 Mon Sep 17 00:00:00 2001 From: Kent Gustavsson Date: Sat, 4 Jan 2020 19:19:29 +0100 Subject: [PATCH 218/353] iio: humidity: dht11 remove TODO since it doesn't make sense DHT11 isn't addressable and will trigger temperature measurement on any data sent on the bus. Signed-off-by: Kent Gustavsson Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/dht11.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c index b459600e1a33..d05c6fdb758b 100644 --- a/drivers/iio/humidity/dht11.c +++ b/drivers/iio/humidity/dht11.c @@ -174,7 +174,6 @@ static irqreturn_t dht11_handle_irq(int irq, void *data) struct iio_dev *iio = data; struct dht11 *dht11 = iio_priv(iio); - /* TODO: Consider making the handler safe for IRQ sharing */ if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) { dht11->edges[dht11->num_edges].ts = ktime_get_boottime_ns(); dht11->edges[dht11->num_edges++].value = From 4766897a9d3bd6af171cdc5ff140e8d132d62d40 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Fri, 3 Jan 2020 17:29:08 -0800 Subject: [PATCH 219/353] iio: chemical: atlas-sensor: add helper function atlas_buffer_num_channels() Add helper function to detect the number of channels to output in trigger handler. This is based on IIO_TIMESTAMP channel being the delimiter between input and output channels. Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/chemical/atlas-sensor.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c index 99095c80531b..2f0a6fed2589 100644 --- a/drivers/iio/chemical/atlas-sensor.c +++ b/drivers/iio/chemical/atlas-sensor.c @@ -86,6 +86,16 @@ static const struct regmap_config atlas_regmap_config = { .val_bits = 8, }; +static int atlas_buffer_num_channels(const struct iio_chan_spec *spec) +{ + int idx = 0; + + for (; spec->type != IIO_TIMESTAMP; spec++) + idx++; + + return idx; +}; + static const struct iio_chan_spec atlas_ph_channels[] = { { .type = IIO_PH, @@ -354,11 +364,12 @@ static irqreturn_t atlas_trigger_handler(int irq, void *private) struct iio_poll_func *pf = private; struct iio_dev *indio_dev = pf->indio_dev; struct atlas_data *data = iio_priv(indio_dev); + int channels = atlas_buffer_num_channels(data->chip->channels); int ret; ret = regmap_bulk_read(data->regmap, data->chip->data_reg, (u8 *) &data->buffer, - sizeof(__be32) * (data->chip->num_channels - 2)); + sizeof(__be32) * channels); if (!ret) iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, From a2dd9bd9334efb8dc0bdc0109abff3a7b57effb1 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 2 Jan 2020 09:36:29 +0100 Subject: [PATCH 220/353] iio: imu: st_lsm6dsx: check return value from st_lsm6dsx_sensor_set_enable Add missing return value check in st_lsm6dsx_read_oneshot disabling the sensor. The issue is reported by coverity with the following error: Unchecked return value: If the function returns an error value, the error value may be mistaken for a normal value. Addresses-Coverity-ID: 1446733 ("Unchecked return value") Fixes: b5969abfa8b8 ("iio: imu: st_lsm6dsx: add motion events") Fixes: 290a6ce11d93 ("iio: imu: add support to lsm6dsx driver") Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index d205b994a9e0..f3ad5694437a 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -1555,8 +1555,11 @@ static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor, if (err < 0) return err; - if (!hw->enable_event) - st_lsm6dsx_sensor_set_enable(sensor, false); + if (!hw->enable_event) { + err = st_lsm6dsx_sensor_set_enable(sensor, false); + if (err < 0) + return err; + } *val = (s16)le16_to_cpu(data); From e825070f697abddf3b9b0a675ed0ff1884114818 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 17 Dec 2019 19:10:38 +0200 Subject: [PATCH 221/353] iio: st_gyro: Correct data for LSM9DS0 gyro The commit 41c128cb25ce ("iio: st_gyro: Add lsm9ds0-gyro support") assumes that gyro in LSM9DS0 is the same as others with 0xd4 WAI ID, but datasheet tells slight different story, i.e. the first scale factor for the chip is 245 dps, and not 250 dps. Correct this by introducing a separate settings for LSM9DS0. Fixes: 41c128cb25ce ("iio: st_gyro: Add lsm9ds0-gyro support") Depends-on: 45a4e4220bf4 ("iio: gyro: st_gyro: fix L3GD20H support") Cc: Leonard Crestez Cc: Lorenzo Bianconi Cc: Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/st_gyro_core.c | 75 ++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index 57be68b291fa..26c50b24bc08 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -138,7 +138,6 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { [2] = LSM330DLC_GYRO_DEV_NAME, [3] = L3G4IS_GYRO_DEV_NAME, [4] = LSM330_GYRO_DEV_NAME, - [5] = LSM9DS0_GYRO_DEV_NAME, }, .ch = (struct iio_chan_spec *)st_gyro_16bit_channels, .odr = { @@ -208,6 +207,80 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { .multi_read_bit = true, .bootime = 2, }, + { + .wai = 0xd4, + .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, + .sensors_supported = { + [0] = LSM9DS0_GYRO_DEV_NAME, + }, + .ch = (struct iio_chan_spec *)st_gyro_16bit_channels, + .odr = { + .addr = 0x20, + .mask = GENMASK(7, 6), + .odr_avl = { + { .hz = 95, .value = 0x00, }, + { .hz = 190, .value = 0x01, }, + { .hz = 380, .value = 0x02, }, + { .hz = 760, .value = 0x03, }, + }, + }, + .pw = { + .addr = 0x20, + .mask = BIT(3), + .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, + }, + .enable_axis = { + .addr = ST_SENSORS_DEFAULT_AXIS_ADDR, + .mask = ST_SENSORS_DEFAULT_AXIS_MASK, + }, + .fs = { + .addr = 0x23, + .mask = GENMASK(5, 4), + .fs_avl = { + [0] = { + .num = ST_GYRO_FS_AVL_245DPS, + .value = 0x00, + .gain = IIO_DEGREE_TO_RAD(8750), + }, + [1] = { + .num = ST_GYRO_FS_AVL_500DPS, + .value = 0x01, + .gain = IIO_DEGREE_TO_RAD(17500), + }, + [2] = { + .num = ST_GYRO_FS_AVL_2000DPS, + .value = 0x02, + .gain = IIO_DEGREE_TO_RAD(70000), + }, + }, + }, + .bdu = { + .addr = 0x23, + .mask = BIT(7), + }, + .drdy_irq = { + .int2 = { + .addr = 0x22, + .mask = BIT(3), + }, + /* + * The sensor has IHL (active low) and open + * drain settings, but only for INT1 and not + * for the DRDY line on INT2. + */ + .stat_drdy = { + .addr = ST_SENSORS_DEFAULT_STAT_ADDR, + .mask = GENMASK(2, 0), + }, + }, + .sim = { + .addr = 0x23, + .value = BIT(0), + }, + .multi_read_bit = true, + .bootime = 2, + }, { .wai = 0xd7, .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS, From efc78983d21aeaf692006d42b92a006cdce3ed4d Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 19:38:52 +0200 Subject: [PATCH 222/353] iio: st_sensors: Drop redundant parameter from st_sensors_of_name_probe() Since we have access to the struct device_driver and thus to the ID table, there is no need to supply special parameters to st_sensors_of_name_probe(). Besides that we have a common API to get driver match data, there is no need to do matching separately for OF and ACPI. Taking into consideration above, simplify the ST sensors code. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_spi.c | 3 +- .../iio/common/st_sensors/st_sensors_core.c | 54 +++++++++---------- .../iio/common/st_sensors/st_sensors_i2c.c | 21 -------- drivers/iio/gyro/st_gyro_i2c.c | 3 +- drivers/iio/gyro/st_gyro_spi.c | 3 +- drivers/iio/magnetometer/st_magn_i2c.c | 3 +- drivers/iio/magnetometer/st_magn_spi.c | 3 +- drivers/iio/pressure/st_pressure_i2c.c | 14 +---- drivers/iio/pressure/st_pressure_spi.c | 3 +- include/linux/iio/common/st_sensors.h | 12 +---- include/linux/iio/common/st_sensors_i2c.h | 10 ---- 11 files changed, 33 insertions(+), 96 deletions(-) diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index 8af7027d5598..3e25268638e2 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -107,8 +107,7 @@ static int st_accel_spi_probe(struct spi_device *spi) struct iio_dev *indio_dev; int err; - st_sensors_of_name_probe(&spi->dev, st_accel_of_match, - spi->modalias, sizeof(spi->modalias)); + st_sensors_dev_name_probe(&spi->dev, spi->modalias, sizeof(spi->modalias)); settings = st_accel_get_settings(spi->modalias); if (!settings) { diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 4a3064fb6cd9..42a71a50650f 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -340,35 +341,6 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, return pdata; } - -/** - * st_sensors_of_name_probe() - device tree probe for ST sensor name - * @dev: driver model representation of the device. - * @match: the OF match table for the device, containing compatible strings - * but also a .data field with the corresponding internal kernel name - * used by this sensor. - * @name: device name buffer reference. - * @len: device name buffer length. - * - * In effect this function matches a compatible string to an internal kernel - * name for a certain sensor device, so that the rest of the autodetection can - * rely on that name from this point on. I2C/SPI devices will be renamed - * to match the internal kernel convention. - */ -void st_sensors_of_name_probe(struct device *dev, - const struct of_device_id *match, - char *name, int len) -{ - const struct of_device_id *of_id; - - of_id = of_match_device(match, dev); - if (!of_id || !of_id->data) - return; - - /* The name from the OF match takes precedence if present */ - strlcpy(name, of_id->data, len); -} -EXPORT_SYMBOL(st_sensors_of_name_probe); #else static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, struct st_sensors_platform_data *defdata) @@ -377,6 +349,30 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, } #endif +/** + * st_sensors_dev_name_probe() - device probe for ST sensor name + * @dev: driver model representation of the device. + * @name: device name buffer reference. + * @len: device name buffer length. + * + * In effect this function matches an ID to an internal kernel + * name for a certain sensor device, so that the rest of the autodetection can + * rely on that name from this point on. I2C/SPI devices will be renamed + * to match the internal kernel convention. + */ +void st_sensors_dev_name_probe(struct device *dev, char *name, int len) +{ + const void *match; + + match = device_get_match_data(dev); + if (!match) + return; + + /* The name from the match takes precedence if present */ + strlcpy(name, match, len); +} +EXPORT_SYMBOL(st_sensors_dev_name_probe); + int st_sensors_init_sensor(struct iio_dev *indio_dev, struct st_sensors_platform_data *pdata) { diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c index aa89d54a7c59..286830fb5d35 100644 --- a/drivers/iio/common/st_sensors/st_sensors_i2c.c +++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c @@ -11,8 +11,6 @@ #include #include #include -#include -#include #include #include @@ -68,25 +66,6 @@ int st_sensors_i2c_configure(struct iio_dev *indio_dev, } EXPORT_SYMBOL(st_sensors_i2c_configure); -#ifdef CONFIG_ACPI -int st_sensors_match_acpi_device(struct device *dev) -{ - const struct acpi_device_id *acpi_id; - kernel_ulong_t driver_data = 0; - - if (ACPI_HANDLE(dev)) { - acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); - if (!acpi_id) { - dev_err(dev, "No driver data\n"); - return -EINVAL; - } - driver_data = acpi_id->driver_data; - } - return driver_data; -} -EXPORT_SYMBOL(st_sensors_match_acpi_device); -#endif - MODULE_AUTHOR("Denis Ciocca "); MODULE_DESCRIPTION("STMicroelectronics ST-sensors i2c driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index 05a1a0874bd5..bc0010835ac0 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -70,8 +70,7 @@ static int st_gyro_i2c_probe(struct i2c_client *client, struct iio_dev *indio_dev; int err; - st_sensors_of_name_probe(&client->dev, st_gyro_of_match, - client->name, sizeof(client->name)); + st_sensors_dev_name_probe(&client->dev, client->name, sizeof(client->name)); settings = st_gyro_get_settings(client->name); if (!settings) { diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index b5c624251231..07224d5bf299 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -74,8 +74,7 @@ static int st_gyro_spi_probe(struct spi_device *spi) struct iio_dev *indio_dev; int err; - st_sensors_of_name_probe(&spi->dev, st_gyro_of_match, - spi->modalias, sizeof(spi->modalias)); + st_sensors_dev_name_probe(&spi->dev, spi->modalias, sizeof(spi->modalias)); settings = st_gyro_get_settings(spi->modalias); if (!settings) { diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index fdba480a12be..bf63777bbc6e 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -62,8 +62,7 @@ static int st_magn_i2c_probe(struct i2c_client *client, struct iio_dev *indio_dev; int err; - st_sensors_of_name_probe(&client->dev, st_magn_of_match, - client->name, sizeof(client->name)); + st_sensors_dev_name_probe(&client->dev, client->name, sizeof(client->name)); settings = st_magn_get_settings(client->name); if (!settings) { diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c index fbf909bde841..78f846fc120e 100644 --- a/drivers/iio/magnetometer/st_magn_spi.c +++ b/drivers/iio/magnetometer/st_magn_spi.c @@ -56,8 +56,7 @@ static int st_magn_spi_probe(struct spi_device *spi) struct iio_dev *indio_dev; int err; - st_sensors_of_name_probe(&spi->dev, st_magn_of_match, - spi->modalias, sizeof(spi->modalias)); + st_sensors_dev_name_probe(&spi->dev, spi->modalias, sizeof(spi->modalias)); settings = st_magn_get_settings(spi->modalias); if (!settings) { diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index 6203bc9d5c2d..dd1f515ca1f1 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -83,18 +82,7 @@ static int st_press_i2c_probe(struct i2c_client *client, struct iio_dev *indio_dev; int ret; - if (client->dev.of_node) { - st_sensors_of_name_probe(&client->dev, st_press_of_match, - client->name, sizeof(client->name)); - } else if (ACPI_HANDLE(&client->dev)) { - ret = st_sensors_match_acpi_device(&client->dev); - if ((ret < 0) || (ret >= ST_PRESS_MAX)) - return -ENODEV; - - strlcpy(client->name, st_press_id_table[ret].name, - sizeof(client->name)); - } else if (!id) - return -ENODEV; + st_sensors_dev_name_probe(&client->dev, client->name, sizeof(client->name)); settings = st_press_get_settings(client->name); if (!settings) { diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c index 7c8b70221e70..dd31241bf4b4 100644 --- a/drivers/iio/pressure/st_pressure_spi.c +++ b/drivers/iio/pressure/st_pressure_spi.c @@ -66,8 +66,7 @@ static int st_press_spi_probe(struct spi_device *spi) struct iio_dev *indio_dev; int err; - st_sensors_of_name_probe(&spi->dev, st_press_of_match, - spi->modalias, sizeof(spi->modalias)); + st_sensors_dev_name_probe(&spi->dev, spi->modalias, sizeof(spi->modalias)); settings = st_press_get_settings(spi->modalias); if (!settings) { diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 686be532f4cb..33e939977444 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -315,16 +315,6 @@ ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev, ssize_t st_sensors_sysfs_scale_avail(struct device *dev, struct device_attribute *attr, char *buf); -#ifdef CONFIG_OF -void st_sensors_of_name_probe(struct device *dev, - const struct of_device_id *match, - char *name, int len); -#else -static inline void st_sensors_of_name_probe(struct device *dev, - const struct of_device_id *match, - char *name, int len) -{ -} -#endif +void st_sensors_dev_name_probe(struct device *dev, char *name, int len); #endif /* ST_SENSORS_H */ diff --git a/include/linux/iio/common/st_sensors_i2c.h b/include/linux/iio/common/st_sensors_i2c.h index 01e424e2af4f..5f15cf01036c 100644 --- a/include/linux/iio/common/st_sensors_i2c.h +++ b/include/linux/iio/common/st_sensors_i2c.h @@ -12,18 +12,8 @@ #include #include -#include int st_sensors_i2c_configure(struct iio_dev *indio_dev, struct i2c_client *client); -#ifdef CONFIG_ACPI -int st_sensors_match_acpi_device(struct device *dev); -#else -static inline int st_sensors_match_acpi_device(struct device *dev) -{ - return -ENODEV; -} -#endif - #endif /* ST_SENSORS_I2C_H */ From ecb27c5e430785018199dd42e566711022d32523 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 16 Dec 2019 19:38:53 +0200 Subject: [PATCH 223/353] iio: st_sensors: Make use of device properties Device property API allows to gather device resources from different sources, such as ACPI. Convert the drivers to unleash the power of device property API. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_i2c.c | 6 +----- drivers/iio/accel/st_accel_spi.c | 6 +----- .../iio/common/st_sensors/st_sensors_core.c | 21 +++++-------------- .../iio/common/st_sensors/st_sensors_spi.c | 12 ++++++----- drivers/iio/gyro/st_gyro_i2c.c | 6 +----- drivers/iio/gyro/st_gyro_spi.c | 6 +----- drivers/iio/magnetometer/st_magn_i2c.c | 6 +----- drivers/iio/magnetometer/st_magn_spi.c | 6 +----- drivers/iio/pressure/st_pressure_i2c.c | 6 +----- drivers/iio/pressure/st_pressure_spi.c | 6 +----- 10 files changed, 20 insertions(+), 61 deletions(-) diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index 0f4aef5448e7..633955d764cc 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -18,7 +18,6 @@ #include #include "st_accel.h" -#ifdef CONFIG_OF static const struct of_device_id st_accel_of_match[] = { { /* An older compatible */ @@ -108,9 +107,6 @@ static const struct of_device_id st_accel_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, st_accel_of_match); -#else -#define st_accel_of_match NULL -#endif #ifdef CONFIG_ACPI static const struct acpi_device_id st_accel_acpi_match[] = { @@ -193,7 +189,7 @@ static int st_accel_i2c_remove(struct i2c_client *client) static struct i2c_driver st_accel_driver = { .driver = { .name = "st-accel-i2c", - .of_match_table = of_match_ptr(st_accel_of_match), + .of_match_table = st_accel_of_match, .acpi_match_table = ACPI_PTR(st_accel_acpi_match), }, .probe_new = st_accel_i2c_probe, diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index 3e25268638e2..568ff1bae0ee 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -17,7 +17,6 @@ #include #include "st_accel.h" -#ifdef CONFIG_OF /* * For new single-chip sensors use as compatible string. * For old single-chip devices keep -accel to maintain @@ -96,9 +95,6 @@ static const struct of_device_id st_accel_of_match[] = { {} }; MODULE_DEVICE_TABLE(of, st_accel_of_match); -#else -#define st_accel_of_match NULL -#endif static int st_accel_spi_probe(struct spi_device *spi) { @@ -165,7 +161,7 @@ MODULE_DEVICE_TABLE(spi, st_accel_id_table); static struct spi_driver st_accel_driver = { .driver = { .name = "st-accel-spi", - .of_match_table = of_match_ptr(st_accel_of_match), + .of_match_table = st_accel_of_match, }, .probe = st_accel_spi_probe, .remove = st_accel_spi_remove, diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 42a71a50650f..e051edbc43c1 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -14,8 +14,6 @@ #include #include #include -#include -#include #include #include #include @@ -320,34 +318,25 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, return 0; } -#ifdef CONFIG_OF -static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, +static struct st_sensors_platform_data *st_sensors_dev_probe(struct device *dev, struct st_sensors_platform_data *defdata) { struct st_sensors_platform_data *pdata; - struct device_node *np = dev->of_node; u32 val; - if (!np) + if (!dev_fwnode(dev)) return NULL; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!of_property_read_u32(np, "st,drdy-int-pin", &val) && (val <= 2)) + if (!device_property_read_u32(dev, "st,drdy-int-pin", &val) && (val <= 2)) pdata->drdy_int_pin = (u8) val; else pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0; - pdata->open_drain = of_property_read_bool(np, "drive-open-drain"); + pdata->open_drain = device_property_read_bool(dev, "drive-open-drain"); return pdata; } -#else -static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, - struct st_sensors_platform_data *defdata) -{ - return NULL; -} -#endif /** * st_sensors_dev_name_probe() - device probe for ST sensor name @@ -381,7 +370,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, int err = 0; /* If OF/DT pdata exists, it will take precedence of anything else */ - of_pdata = st_sensors_of_probe(indio_dev->dev.parent, pdata); + of_pdata = st_sensors_dev_probe(indio_dev->dev.parent, pdata); if (of_pdata) pdata = of_pdata; diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c index 2262f81b07c2..1275fb0eda31 100644 --- a/drivers/iio/common/st_sensors/st_sensors_spi.c +++ b/drivers/iio/common/st_sensors/st_sensors_spi.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -37,14 +38,15 @@ static const struct regmap_config st_sensors_spi_regmap_multiread_bit_config = { */ static bool st_sensors_is_spi_3_wire(struct spi_device *spi) { - struct device_node *np = spi->dev.of_node; struct st_sensors_platform_data *pdata; + struct device *dev = &spi->dev; - pdata = (struct st_sensors_platform_data *)spi->dev.platform_data; - if ((np && of_property_read_bool(np, "spi-3wire")) || - (pdata && pdata->spi_3wire)) { + if (device_property_read_bool(dev, "spi-3wire")) + return true; + + pdata = (struct st_sensors_platform_data *)dev->platform_data; + if (pdata && pdata->spi_3wire) return true; - } return false; } diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index bc0010835ac0..8190966e6ff0 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -17,7 +17,6 @@ #include #include "st_gyro.h" -#ifdef CONFIG_OF static const struct of_device_id st_gyro_of_match[] = { { .compatible = "st,l3g4200d-gyro", @@ -58,9 +57,6 @@ static const struct of_device_id st_gyro_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, st_gyro_of_match); -#else -#define st_gyro_of_match NULL -#endif static int st_gyro_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -121,7 +117,7 @@ MODULE_DEVICE_TABLE(i2c, st_gyro_id_table); static struct i2c_driver st_gyro_driver = { .driver = { .name = "st-gyro-i2c", - .of_match_table = of_match_ptr(st_gyro_of_match), + .of_match_table = st_gyro_of_match, }, .probe = st_gyro_i2c_probe, .remove = st_gyro_i2c_remove, diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index 07224d5bf299..efb862763ca3 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -17,7 +17,6 @@ #include #include "st_gyro.h" -#ifdef CONFIG_OF /* * For new single-chip sensors use as compatible string. * For old single-chip devices keep -gyro to maintain @@ -63,9 +62,6 @@ static const struct of_device_id st_gyro_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, st_gyro_of_match); -#else -#define st_gyro_of_match NULL -#endif static int st_gyro_spi_probe(struct spi_device *spi) { @@ -125,7 +121,7 @@ MODULE_DEVICE_TABLE(spi, st_gyro_id_table); static struct spi_driver st_gyro_driver = { .driver = { .name = "st-gyro-spi", - .of_match_table = of_match_ptr(st_gyro_of_match), + .of_match_table = st_gyro_of_match, }, .probe = st_gyro_spi_probe, .remove = st_gyro_spi_remove, diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index bf63777bbc6e..c6bb4ce77594 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -17,7 +17,6 @@ #include #include "st_magn.h" -#ifdef CONFIG_OF static const struct of_device_id st_magn_of_match[] = { { .compatible = "st,lsm303dlh-magn", @@ -50,9 +49,6 @@ static const struct of_device_id st_magn_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, st_magn_of_match); -#else -#define st_magn_of_match NULL -#endif static int st_magn_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -112,7 +108,7 @@ MODULE_DEVICE_TABLE(i2c, st_magn_id_table); static struct i2c_driver st_magn_driver = { .driver = { .name = "st-magn-i2c", - .of_match_table = of_match_ptr(st_magn_of_match), + .of_match_table = st_magn_of_match, }, .probe = st_magn_i2c_probe, .remove = st_magn_i2c_remove, diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c index 78f846fc120e..3d08d74c367d 100644 --- a/drivers/iio/magnetometer/st_magn_spi.c +++ b/drivers/iio/magnetometer/st_magn_spi.c @@ -17,7 +17,6 @@ #include #include "st_magn.h" -#ifdef CONFIG_OF /* * For new single-chip sensors use as compatible string. * For old single-chip devices keep -magn to maintain @@ -45,9 +44,6 @@ static const struct of_device_id st_magn_of_match[] = { {} }; MODULE_DEVICE_TABLE(of, st_magn_of_match); -#else -#define st_magn_of_match NULL -#endif static int st_magn_spi_probe(struct spi_device *spi) { @@ -103,7 +99,7 @@ MODULE_DEVICE_TABLE(spi, st_magn_id_table); static struct spi_driver st_magn_driver = { .driver = { .name = "st-magn-spi", - .of_match_table = of_match_ptr(st_magn_of_match), + .of_match_table = st_magn_of_match, }, .probe = st_magn_spi_probe, .remove = st_magn_spi_remove, diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index dd1f515ca1f1..09c6903f99b8 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -17,7 +17,6 @@ #include #include "st_pressure.h" -#ifdef CONFIG_OF static const struct of_device_id st_press_of_match[] = { { .compatible = "st,lps001wp-press", @@ -50,9 +49,6 @@ static const struct of_device_id st_press_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, st_press_of_match); -#else -#define st_press_of_match NULL -#endif #ifdef CONFIG_ACPI static const struct acpi_device_id st_press_acpi_match[] = { @@ -119,7 +115,7 @@ static int st_press_i2c_remove(struct i2c_client *client) static struct i2c_driver st_press_driver = { .driver = { .name = "st-press-i2c", - .of_match_table = of_match_ptr(st_press_of_match), + .of_match_table = st_press_of_match, .acpi_match_table = ACPI_PTR(st_press_acpi_match), }, .probe = st_press_i2c_probe, diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c index dd31241bf4b4..b5ee3ec2764f 100644 --- a/drivers/iio/pressure/st_pressure_spi.c +++ b/drivers/iio/pressure/st_pressure_spi.c @@ -17,7 +17,6 @@ #include #include "st_pressure.h" -#ifdef CONFIG_OF /* * For new single-chip sensors use as compatible string. * For old single-chip devices keep -press to maintain @@ -55,9 +54,6 @@ static const struct of_device_id st_press_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, st_press_of_match); -#else -#define st_press_of_match NULL -#endif static int st_press_spi_probe(struct spi_device *spi) { @@ -115,7 +111,7 @@ MODULE_DEVICE_TABLE(spi, st_press_id_table); static struct spi_driver st_press_driver = { .driver = { .name = "st-press-spi", - .of_match_table = of_match_ptr(st_press_of_match), + .of_match_table = st_press_of_match, }, .probe = st_press_spi_probe, .remove = st_press_spi_remove, From dc26935fb60e8da8d59655dd2ec0de47b20d7d8f Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Wed, 27 Nov 2019 14:07:29 +0100 Subject: [PATCH 224/353] iio: adc: stm32-dfsdm: fix single conversion Apply data formatting to single conversion, as this is already done in continuous and trigger modes. Fixes: 102afde62937 ("iio: adc: stm32-dfsdm: manage data resolution in trigger mode") Signed-off-by: Olivier Moysan Cc: Acked-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-dfsdm-adc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 74a2211bdff4..1c9b05d11dc5 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -1204,6 +1204,8 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev, stm32_dfsdm_stop_conv(adc); + stm32_dfsdm_process_data(adc, res); + stop_dfsdm: stm32_dfsdm_stop_dfsdm(adc->dfsdm); From f81ec5bf0cab29693980abbc983d0971e0efb0ea Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Wed, 27 Nov 2019 14:10:08 +0100 Subject: [PATCH 225/353] iio: adc: stm32-dfsdm: adapt sampling rate to oversampling ratio Update sampling rate when oversampling ratio is changed through the IIO ABI. Signed-off-by: Olivier Moysan Acked-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-dfsdm-adc.c | 32 ++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 1c9b05d11dc5..2aad2cda6943 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -1221,14 +1221,32 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, unsigned int spi_freq; int ret = -EINVAL; + switch (ch->src) { + case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL: + spi_freq = adc->dfsdm->spi_master_freq; + break; + case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING: + case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING: + spi_freq = adc->dfsdm->spi_master_freq / 2; + break; + default: + spi_freq = adc->spi_freq; + } + switch (mask) { case IIO_CHAN_INFO_OVERSAMPLING_RATIO: ret = iio_device_claim_direct_mode(indio_dev); if (ret) return ret; + ret = stm32_dfsdm_compute_all_osrs(indio_dev, val); - if (!ret) + if (!ret) { + dev_dbg(&indio_dev->dev, + "Sampling rate changed from (%u) to (%u)\n", + adc->sample_freq, spi_freq / val); adc->oversamp = val; + adc->sample_freq = spi_freq / val; + } iio_device_release_direct_mode(indio_dev); return ret; @@ -1240,18 +1258,6 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, if (ret) return ret; - switch (ch->src) { - case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL: - spi_freq = adc->dfsdm->spi_master_freq; - break; - case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING: - case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING: - spi_freq = adc->dfsdm->spi_master_freq / 2; - break; - default: - spi_freq = adc->spi_freq; - } - ret = dfsdm_adc_set_samp_freq(indio_dev, val, spi_freq); iio_device_release_direct_mode(indio_dev); return ret; From a4e6f40c77afe6e6a0076c4bcf7cbf68406a7d9f Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Tue, 10 Dec 2019 16:07:55 +0200 Subject: [PATCH 226/353] iio: imu: adis: use new `delay` structure for SPI transfer delays In a recent change to the SPI subsystem [1], a new `delay` struct was added to replace the `delay_usecs`. This change replaces the current `delay_usecs` with `delay` for this driver. The `spi_transfer_delay_exec()` function [in the SPI framework] makes sure that both `delay_usecs` & `delay` are used (in this order to preserve backwards compatibility). [1] commit bebcfd272df6485 ("spi: introduce `delay` field for `spi_transfer` + spi_transfer_delay_exec()") Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 8f0867495ef5..022bb54fb748 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -45,7 +45,8 @@ int __adis_write_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { @@ -53,7 +54,8 @@ int __adis_write_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { @@ -61,19 +63,22 @@ int __adis_write_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 6, .bits_per_word = 8, .len = 2, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 8, .bits_per_word = 8, .len = 2, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, }, }; @@ -140,7 +145,8 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { @@ -148,7 +154,8 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->read_delay, + .delay.value = adis->data->read_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { @@ -157,14 +164,16 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->read_delay, + .delay.value = adis->data->read_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { .rx_buf = adis->rx + 2, .bits_per_word = 8, .len = 2, - .delay_usecs = adis->data->read_delay, + .delay.value = adis->data->read_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, }, }; From f3c69559b56da786a722aaa3cfe8b317de9f9d61 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Mon, 13 Jan 2020 22:29:39 +0100 Subject: [PATCH 227/353] staging: rtl8188eu: remove unused parameters from rtw_check_network_type Parameters 'ratelen' and 'channel' of function rtw_check_network_type are unused, remove them. Reduces object file size by 62 bytes. text data bss dec hex filename 398525 12896 4688 416109 6596d drivers/staging/rtl8188eu/r8188eu.o 398463 12896 4688 416047 6592f drivers/staging/rtl8188eu/r8188eu.o Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200113212939.9738-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_ap.c | 4 ++-- drivers/staging/rtl8188eu/core/rtw_ieee80211.c | 2 +- drivers/staging/rtl8188eu/include/ieee80211.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index 88e42cc1d837..93283c7deec4 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -429,7 +429,7 @@ static void update_bmc_sta(struct adapter *padapter) /* prepare for add_RATid */ supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates); - network_type = rtw_check_network_type((u8 *)&pcur_network->SupportedRates, supportRateNum, 1); + network_type = rtw_check_network_type((u8 *)&pcur_network->SupportedRates); memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum); psta->bssratelen = supportRateNum; @@ -802,7 +802,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) supportRateNum += ie_len; } - network_type = rtw_check_network_type(supportRate, supportRateNum, channel); + network_type = rtw_check_network_type(supportRate); rtw_set_supported_rate(pbss_network->SupportedRates, network_type); diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index cc1b5438c04c..1344d369e05d 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -98,7 +98,7 @@ bool rtw_is_cckratesonly_included(u8 *rate) return true; } -int rtw_check_network_type(unsigned char *rate, int ratelen, int channel) +int rtw_check_network_type(unsigned char *rate) { /* could be pure B, pure G, or B/G */ if (rtw_is_cckratesonly_included(rate)) diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h index d569fe5ed8e6..75f0ebe0faf5 100644 --- a/drivers/staging/rtl8188eu/include/ieee80211.h +++ b/drivers/staging/rtl8188eu/include/ieee80211.h @@ -765,7 +765,7 @@ bool rtw_is_cckrates_included(u8 *rate); bool rtw_is_cckratesonly_included(u8 *rate); -int rtw_check_network_type(unsigned char *rate, int ratelen, int channel); +int rtw_check_network_type(unsigned char *rate); void rtw_get_bcn_info(struct wlan_network *pnetwork); From d85cad420a21e28016248ef9939d20c1264246eb Mon Sep 17 00:00:00 2001 From: Pragat Pandya Date: Sat, 11 Jan 2020 19:52:33 +0530 Subject: [PATCH 228/353] staging: exfat: Fix alignment warnings Fix checkpatch warning "Alignment should match open parenthesis". Signed-off-by: Pragat Pandya Link: https://lore.kernel.org/r/20200111142233.11354-1-pragat.pandya@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_blkdev.c | 4 ++-- drivers/staging/exfat/exfat_core.c | 29 ++++++++++++++-------------- drivers/staging/exfat/exfat_super.c | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/staging/exfat/exfat_blkdev.c b/drivers/staging/exfat/exfat_blkdev.c index 8791a5f2bb08..0a3dc3568293 100644 --- a/drivers/staging/exfat/exfat_blkdev.c +++ b/drivers/staging/exfat/exfat_blkdev.c @@ -31,7 +31,7 @@ void exfat_bdev_close(struct super_block *sb) } int exfat_bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh, - u32 num_secs, bool read) + u32 num_secs, bool read) { struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); @@ -66,7 +66,7 @@ int exfat_bdev_read(struct super_block *sb, sector_t secno, struct buffer_head * } int exfat_bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh, - u32 num_secs, bool sync) + u32 num_secs, bool sync) { s32 count; struct buffer_head *bh2; diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c index 5e7645fe8c45..36a4102c057d 100644 --- a/drivers/staging/exfat/exfat_core.c +++ b/drivers/staging/exfat/exfat_core.c @@ -250,7 +250,7 @@ static u32 test_alloc_bitmap(struct super_block *sb, u32 clu) } static s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, - struct chain_t *p_chain) + struct chain_t *p_chain) { s32 num_clusters = 0; u32 hint_clu, new_clu, last_clu = CLUSTER_32(~0); @@ -329,7 +329,7 @@ static s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, } static void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, - s32 do_relse) + s32 do_relse) { s32 num_clusters = 0; u32 clu; @@ -920,7 +920,7 @@ static void exfat_set_entry_size(struct dentry_t *p_entry, u64 size) } static void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, - u8 mode) + u8 mode) { u16 t = 0x00, d = 0x21; struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; @@ -949,7 +949,7 @@ static void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *t } static void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, - u8 mode) + u8 mode) { u16 t, d; struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; @@ -1013,7 +1013,7 @@ static void init_name_entry(struct name_dentry_t *ep, u16 *uniname) } static s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, - s32 entry, u32 type, u32 start_clu, u64 size) + s32 entry, u32 type, u32 start_clu, u64 size) { sector_t sector; u8 flags; @@ -1089,7 +1089,7 @@ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir, } static void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, - s32 entry, s32 order, s32 num_entries) + s32 entry, s32 order, s32 num_entries) { int i; sector_t sector; @@ -1256,7 +1256,7 @@ static s32 _walk_fat_chain(struct super_block *sb, struct chain_t *p_dir, } static s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry, - sector_t *sector, s32 *offset) + sector_t *sector, s32 *offset) { s32 off, ret; u32 clu = 0; @@ -1492,7 +1492,8 @@ void release_entry_set(struct entry_set_cache_t *es) /* search EMPTY CONTINUOUS "num_entries" entries */ static s32 search_deleted_or_unused_entry(struct super_block *sb, - struct chain_t *p_dir, s32 num_entries) + struct chain_t *p_dir, + s32 num_entries) { int i, dentry, num_empty = 0; s32 dentries_per_clu; @@ -1668,7 +1669,7 @@ static s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_ } static s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *uniname, - s32 order) + s32 order) { int i, len = 0; @@ -1690,8 +1691,8 @@ static s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *unina * -2 : entry with the name does not exist */ static s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, - struct uni_name_t *p_uniname, s32 num_entries, - struct dos_name_t *p_dosname, u32 type) + struct uni_name_t *p_uniname, s32 num_entries, + struct dos_name_t *p_dosname, u32 type) { int i = 0, dentry = 0, num_ext_entries = 0, len, step; s32 order = 0; @@ -1833,7 +1834,7 @@ static s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, } static s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, - s32 entry, struct dentry_t *p_entry) + s32 entry, struct dentry_t *p_entry) { int i, count = 0; u32 type; @@ -1996,8 +1997,8 @@ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir, } static void exfat_get_uni_name_from_ext_entry(struct super_block *sb, - struct chain_t *p_dir, s32 entry, - u16 *uniname) + struct chain_t *p_dir, s32 entry, + u16 *uniname) { int i; struct dentry_t *ep; diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 9fa2ad3627c5..128ca4403d03 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -365,7 +365,7 @@ static int ffsMountVol(struct super_block *sb) if (p_bd->sector_size < sb->s_blocksize) { printk(KERN_INFO "EXFAT: mount failed - sector size %d less than blocksize %ld\n", - p_bd->sector_size, sb->s_blocksize); + p_bd->sector_size, sb->s_blocksize); ret = -EINVAL; goto out; } From 98ab51df76bf4a317a0116d6c940fa08c6f12322 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 10 Jan 2020 22:04:56 +0100 Subject: [PATCH 229/353] staging: rtl8723bs: remove ODM_GetRightChnlPlaceforIQK() Function ODM_GetRightChnlPlaceforIQK() returns non-zero values only for channels > 14. According to the TODO code valid only for 5 GHz should be removed. - find and remove remaining code valid only for 5 GHz. Most of the obvious ones have been removed, but things like channel > 14 still exist. Remove ODM_GetRightChnlPlaceforIQK() and replace the uses of the return value with zero. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200110210456.13178-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/HalPhyRf.c | 30 ------------------- drivers/staging/rtl8723bs/hal/HalPhyRf.h | 8 ----- .../staging/rtl8723bs/hal/HalPhyRf_8723B.c | 11 +++---- 3 files changed, 4 insertions(+), 45 deletions(-) diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf.c b/drivers/staging/rtl8723bs/hal/HalPhyRf.c index beb4002a40e1..357802db9aed 100644 --- a/drivers/staging/rtl8723bs/hal/HalPhyRf.c +++ b/drivers/staging/rtl8723bs/hal/HalPhyRf.c @@ -622,33 +622,3 @@ void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter) pDM_Odm->RFCalibrateInfo.TXPowercount = 0; } - - - - -/* 3 ============================================================ */ -/* 3 IQ Calibration */ -/* 3 ============================================================ */ - -u8 ODM_GetRightChnlPlaceforIQK(u8 chnl) -{ - u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, - 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, - 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, - 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, - 161, 163, 165 - }; - u8 place = chnl; - - - if (chnl > 14) { - for (place = 14; place < sizeof(channel_all); place++) { - if (channel_all[place] == chnl) - return place-13; - } - } - return 0; - -} diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf.h b/drivers/staging/rtl8723bs/hal/HalPhyRf.h index 3d6f68bc61d7..643fcf37c9ad 100644 --- a/drivers/staging/rtl8723bs/hal/HalPhyRf.h +++ b/drivers/staging/rtl8723bs/hal/HalPhyRf.h @@ -44,12 +44,4 @@ void ODM_ClearTxPowerTrackingState(PDM_ODM_T pDM_Odm); void ODM_TXPowerTrackingCallback_ThermalMeter(struct adapter *Adapter); - - -#define ODM_TARGET_CHNL_NUM_2G_5G 59 - - -u8 ODM_GetRightChnlPlaceforIQK(u8 chnl); - - #endif /* #ifndef __HAL_PHY_RF_H__ */ diff --git a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c index 338dd0b7a6eb..85ea535dd6e9 100644 --- a/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c +++ b/drivers/staging/rtl8723bs/hal/HalPhyRf_8723B.c @@ -1792,7 +1792,7 @@ void PHY_IQCalibrate_8723B( PDM_ODM_T pDM_Odm = &pHalData->odmpriv; s32 result[4][8]; /* last is final result */ - u8 i, final_candidate, Indexforchannel; + u8 i, final_candidate; bool bPathAOK, bPathBOK; s32 RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC, RegTmp = 0; bool is12simular, is13simular, is23simular; @@ -1997,17 +1997,14 @@ void PHY_IQCalibrate_8723B( _PHY_PathBFillIQKMatrix8723B(padapter, bPathBOK, result, final_candidate, (RegEC4 == 0)); } - Indexforchannel = ODM_GetRightChnlPlaceforIQK(pHalData->CurrentChannel); - /* To Fix BSOD when final_candidate is 0xff */ /* by sherry 20120321 */ if (final_candidate < 4) { for (i = 0; i < IQK_Matrix_REG_NUM; i++) - pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[Indexforchannel].Value[0][i] = result[final_candidate][i]; - pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[Indexforchannel].bIQKDone = true; + pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[0].Value[0][i] = result[final_candidate][i]; + pDM_Odm->RFCalibrateInfo.IQKMatrixRegSetting[0].bIQKDone = true; } - /* RT_DISP(FINIT, INIT_IQK, ("\nIQK OK Indexforchannel %d.\n", Indexforchannel)); */ - ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("\nIQK OK Indexforchannel %d.\n", Indexforchannel)); + ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("\nIQK OK Indexforchannel %d.\n", 0)); _PHY_SaveADDARegisters8723B(padapter, IQK_BB_REG_92C, pDM_Odm->RFCalibrateInfo.IQK_BB_backup_recover, 9); From c0a6bf0f1ae33eddd36e8201ef132c1abc4c19bf Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Tue, 14 Jan 2020 14:44:18 +0100 Subject: [PATCH 230/353] staging: rtl8188eu: refactor rtw_hal_antdiv_before_linked() Refactor rtw_hal_antdiv_before_linked() to clear checkpatch warnings. WARNING: line over 80 characters WARNING: else is not generally useful after a break or return Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200114134422.13598-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rtl8188e_dm.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 545d6a6102f1..0aa5e9346787 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -197,15 +197,16 @@ u8 rtw_hal_antdiv_before_linked(struct adapter *Adapter) if (check_fwstate(pmlmepriv, _FW_LINKED)) return false; - if (dm_swat_tbl->SWAS_NoLink_State == 0) { - /* switch channel */ - dm_swat_tbl->SWAS_NoLink_State = 1; - dm_swat_tbl->CurAntenna = (dm_swat_tbl->CurAntenna == Antenna_A) ? Antenna_B : Antenna_A; - - rtw_antenna_select_cmd(Adapter, dm_swat_tbl->CurAntenna, false); - return true; - } else { + if (dm_swat_tbl->SWAS_NoLink_State != 0) { dm_swat_tbl->SWAS_NoLink_State = 0; return false; } + + /* switch channel */ + dm_swat_tbl->SWAS_NoLink_State = 1; + dm_swat_tbl->CurAntenna = (dm_swat_tbl->CurAntenna == Antenna_A) ? + Antenna_B : Antenna_A; + + rtw_antenna_select_cmd(Adapter, dm_swat_tbl->CurAntenna, false); + return true; } From cdc7fa32325ce6f834c46bd7e710418655af58c6 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Tue, 14 Jan 2020 14:44:19 +0100 Subject: [PATCH 231/353] staging: rtl8188eu: convert rtw_hal_antdiv_before_linked() to bool Function rtw_hal_antdiv_before_linked() returns boolean values, so change the return type from u8 to bool. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200114134422.13598-2-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rtl8188e_dm.c | 2 +- drivers/staging/rtl8188eu/include/hal_intf.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 0aa5e9346787..756945d41412 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -184,7 +184,7 @@ void rtw_hal_antdiv_rssi_compared(struct adapter *Adapter, struct wlan_bssid_ex } /* Add new function to reset the state of antenna diversity before link. */ -u8 rtw_hal_antdiv_before_linked(struct adapter *Adapter) +bool rtw_hal_antdiv_before_linked(struct adapter *Adapter) { struct odm_dm_struct *dm_odm = &Adapter->HalData->odmpriv; struct sw_ant_switch *dm_swat_tbl = &dm_odm->DM_SWAT_Table; diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 516a89647003..39df30599a5d 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -209,7 +209,7 @@ void rtw_hal_set_bwmode(struct adapter *padapter, void rtw_hal_set_chan(struct adapter *padapter, u8 channel); void rtw_hal_dm_watchdog(struct adapter *padapter); -u8 rtw_hal_antdiv_before_linked(struct adapter *padapter); +bool rtw_hal_antdiv_before_linked(struct adapter *padapter); void rtw_hal_antdiv_rssi_compared(struct adapter *padapter, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src); From c085fed4cbb522a8859c10a3d04e293793cf7935 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Tue, 14 Jan 2020 14:44:20 +0100 Subject: [PATCH 232/353] staging: rtl8188eu: cleanup long lines in rtl8188e_dm.c Cleanup lines over 80 characters in rtl8188e_dm.c by adding appropriate line breaks. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200114134422.13598-3-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rtl8188e_dm.c | 26 ++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 756945d41412..36255199633a 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -51,8 +51,10 @@ static void Init_ODM_ComInfo_88E(struct adapter *Adapter) dm_odm->AntDivType = hal_data->TRxAntDivType; - /* Tx power tracking BB swing table. */ - /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */ + /* Tx power tracking BB swing table. + * The base index = + * 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB + */ dm_odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */ dm_odm->BbSwingIdxOfdmCurrent = 12; dm_odm->BbSwingFlagOfdm = false; @@ -106,14 +108,17 @@ static void Update_ODM_ComInfo_88E(struct adapter *Adapter) dm_odm->pbPowerSaving = (bool *)&pwrctrlpriv->bpower_saving; dm_odm->AntDivType = hal_data->TRxAntDivType; - /* Tx power tracking BB swing table. */ - /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */ + /* Tx power tracking BB swing table. + * The base index = + * 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB + */ dm_odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */ dm_odm->BbSwingIdxOfdmCurrent = 12; dm_odm->BbSwingFlagOfdm = false; for (i = 0; i < NUM_STA; i++) - ODM_CmnInfoPtrArrayHook(dm_odm, ODM_CMNINFO_STA_STATUS, i, NULL); + ODM_CmnInfoPtrArrayHook(dm_odm, ODM_CMNINFO_STA_STATUS, i, + NULL); } void rtl8188e_InitHalDm(struct adapter *Adapter) @@ -172,13 +177,18 @@ void rtw_hal_dm_init(struct adapter *Adapter) /* Add new function to reset the state of antenna diversity before link. */ /* Compare RSSI for deciding antenna */ -void rtw_hal_antdiv_rssi_compared(struct adapter *Adapter, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src) +void rtw_hal_antdiv_rssi_compared(struct adapter *Adapter, + struct wlan_bssid_ex *dst, + struct wlan_bssid_ex *src) { if (Adapter->HalData->AntDivCfg != 0) { - /* select optimum_antenna for before linked =>For antenna diversity */ + /* select optimum_antenna for before linked => For antenna + * diversity + */ if (dst->Rssi >= src->Rssi) {/* keep org parameter */ src->Rssi = dst->Rssi; - src->PhyInfo.Optimum_antenna = dst->PhyInfo.Optimum_antenna; + src->PhyInfo.Optimum_antenna = + dst->PhyInfo.Optimum_antenna; } } } From 8c26f783d786423a4683ef4c19bef411b13c4d39 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Tue, 14 Jan 2020 14:44:21 +0100 Subject: [PATCH 233/353] staging: rtl8188eu: remove unnecessary parentheses in rtl8188e_dm.c Remove unnecessary parentheses reported by checkpatch. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200114134422.13598-4-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rtl8188e_dm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 36255199633a..5348db2725a1 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -36,7 +36,7 @@ static void Init_ODM_ComInfo_88E(struct adapter *Adapter) { struct hal_data_8188e *hal_data = Adapter->HalData; struct dm_priv *pdmpriv = &hal_data->dmpriv; - struct odm_dm_struct *dm_odm = &(hal_data->odmpriv); + struct odm_dm_struct *dm_odm = &hal_data->odmpriv; /* Init Value */ memset(dm_odm, 0, sizeof(*dm_odm)); @@ -71,7 +71,7 @@ static void Update_ODM_ComInfo_88E(struct adapter *Adapter) struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv; struct hal_data_8188e *hal_data = Adapter->HalData; - struct odm_dm_struct *dm_odm = &(hal_data->odmpriv); + struct odm_dm_struct *dm_odm = &hal_data->odmpriv; struct dm_priv *pdmpriv = &hal_data->dmpriv; int i; @@ -124,7 +124,7 @@ static void Update_ODM_ComInfo_88E(struct adapter *Adapter) void rtl8188e_InitHalDm(struct adapter *Adapter) { struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv; - struct odm_dm_struct *dm_odm = &(Adapter->HalData->odmpriv); + struct odm_dm_struct *dm_odm = &Adapter->HalData->odmpriv; dm_InitGPIOSetting(Adapter); pdmpriv->DM_Type = DM_Type_ByDriver; @@ -198,7 +198,7 @@ bool rtw_hal_antdiv_before_linked(struct adapter *Adapter) { struct odm_dm_struct *dm_odm = &Adapter->HalData->odmpriv; struct sw_ant_switch *dm_swat_tbl = &dm_odm->DM_SWAT_Table; - struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv); + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; /* Condition that does not need to use antenna diversity. */ if (Adapter->HalData->AntDivCfg == 0) From cdb9c044f92b78557e5e535819a932caeff81668 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Tue, 14 Jan 2020 14:44:22 +0100 Subject: [PATCH 234/353] staging: rtl8188eu: cleanup whitespace in rtl8188e_dm.c Replace tabs with spaces and/or remove spaces to use typical kernel horizontal whitespace. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200114134422.13598-5-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rtl8188e_dm.c | 44 ++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c index 5348db2725a1..241f55b92808 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c @@ -21,7 +21,7 @@ /* Initialize GPIO setting registers */ static void dm_InitGPIOSetting(struct adapter *Adapter) { - u8 tmp1byte; + u8 tmp1byte; tmp1byte = usb_read8(Adapter, REG_GPIO_MUXCFG); tmp1byte &= (GPIOSEL_GPIO | ~GPIOSEL_ENBT); @@ -35,7 +35,7 @@ static void dm_InitGPIOSetting(struct adapter *Adapter) static void Init_ODM_ComInfo_88E(struct adapter *Adapter) { struct hal_data_8188e *hal_data = Adapter->HalData; - struct dm_priv *pdmpriv = &hal_data->dmpriv; + struct dm_priv *pdmpriv = &hal_data->dmpriv; struct odm_dm_struct *dm_odm = &hal_data->odmpriv; /* Init Value */ @@ -59,38 +59,38 @@ static void Init_ODM_ComInfo_88E(struct adapter *Adapter) dm_odm->BbSwingIdxOfdmCurrent = 12; dm_odm->BbSwingFlagOfdm = false; - pdmpriv->InitODMFlag = ODM_RF_CALIBRATION | - ODM_RF_TX_PWR_TRACK; + pdmpriv->InitODMFlag = ODM_RF_CALIBRATION | + ODM_RF_TX_PWR_TRACK; dm_odm->SupportAbility = pdmpriv->InitODMFlag; } static void Update_ODM_ComInfo_88E(struct adapter *Adapter) { - struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; - struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; + struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; + struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv; struct hal_data_8188e *hal_data = Adapter->HalData; struct odm_dm_struct *dm_odm = &hal_data->odmpriv; - struct dm_priv *pdmpriv = &hal_data->dmpriv; + struct dm_priv *pdmpriv = &hal_data->dmpriv; int i; - pdmpriv->InitODMFlag = ODM_BB_DIG | - ODM_BB_RA_MASK | - ODM_BB_DYNAMIC_TXPWR | - ODM_BB_FA_CNT | - ODM_BB_RSSI_MONITOR | - ODM_BB_CCK_PD | - ODM_BB_PWR_SAVE | - ODM_MAC_EDCA_TURBO | - ODM_RF_CALIBRATION | - ODM_RF_TX_PWR_TRACK; + pdmpriv->InitODMFlag = ODM_BB_DIG | + ODM_BB_RA_MASK | + ODM_BB_DYNAMIC_TXPWR | + ODM_BB_FA_CNT | + ODM_BB_RSSI_MONITOR | + ODM_BB_CCK_PD | + ODM_BB_PWR_SAVE | + ODM_MAC_EDCA_TURBO | + ODM_RF_CALIBRATION | + ODM_RF_TX_PWR_TRACK; if (hal_data->AntDivCfg) pdmpriv->InitODMFlag |= ODM_BB_ANT_DIV; if (Adapter->registrypriv.mp_mode == 1) { - pdmpriv->InitODMFlag = ODM_RF_CALIBRATION | - ODM_RF_TX_PWR_TRACK; + pdmpriv->InitODMFlag = ODM_RF_CALIBRATION | + ODM_RF_TX_PWR_TRACK; } dm_odm->SupportAbility = pdmpriv->InitODMFlag; @@ -123,7 +123,7 @@ static void Update_ODM_ComInfo_88E(struct adapter *Adapter) void rtl8188e_InitHalDm(struct adapter *Adapter) { - struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv; + struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv; struct odm_dm_struct *dm_odm = &Adapter->HalData->odmpriv; dm_InitGPIOSetting(Adapter); @@ -167,7 +167,7 @@ skip_dm: void rtw_hal_dm_init(struct adapter *Adapter) { - struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv; + struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv; struct odm_dm_struct *podmpriv = &Adapter->HalData->odmpriv; memset(pdmpriv, 0, sizeof(struct dm_priv)); @@ -185,7 +185,7 @@ void rtw_hal_antdiv_rssi_compared(struct adapter *Adapter, /* select optimum_antenna for before linked => For antenna * diversity */ - if (dst->Rssi >= src->Rssi) {/* keep org parameter */ + if (dst->Rssi >= src->Rssi) {/* keep org parameter */ src->Rssi = dst->Rssi; src->PhyInfo.Optimum_antenna = dst->PhyInfo.Optimum_antenna; From 8297ca5e8c70ddb58cf03cd0411929ab87a44860 Mon Sep 17 00:00:00 2001 From: Ole Wiedemann Date: Fri, 13 Dec 2019 14:10:32 +0100 Subject: [PATCH 235/353] staging: android: ashmem: Replace strcpy with strscpy Replaced strcpy call with safer strscpy call with given length. This elimates the need to manually null-terminate the given string, since strscpy will null terminate the destination anyway.: Signed-off-by: Ole Wiedemann Co-developed-by: Sebastian Scherbel Signed-off-by: Sebastian Scherbel Acked-by: Christian Brauner Acked-by: Joel Fernandes (Google) Acked-by: Todd Kjos Link: https://lore.kernel.org/r/20191213131032.22579-1-ole.wiedemann@fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ashmem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 74d497d39c5a..5891d0744a76 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -537,14 +537,14 @@ static int set_name(struct ashmem_area *asma, void __user *name) len = strncpy_from_user(local_name, name, ASHMEM_NAME_LEN); if (len < 0) return len; - if (len == ASHMEM_NAME_LEN) - local_name[ASHMEM_NAME_LEN - 1] = '\0'; + mutex_lock(&ashmem_mutex); /* cannot change an existing mapping's name */ if (asma->file) ret = -EINVAL; else - strcpy(asma->name + ASHMEM_NAME_PREFIX_LEN, local_name); + strscpy(asma->name + ASHMEM_NAME_PREFIX_LEN, local_name, + ASHMEM_NAME_LEN); mutex_unlock(&ashmem_mutex); return ret; From 4cc41cbce536876678b35e03c4a8a7bb72c78fa9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 14 Jan 2020 18:16:04 +0000 Subject: [PATCH 236/353] staging: wlan-ng: ensure error return is actually returned Currently when the call to prism2sta_ifst fails a netdev_err error is reported, error return variable result is set to -1 but the function always returns 0 for success. Fix this by returning the error value in variable result rather than 0. Addresses-Coverity: ("Unused value") Fixes: 00b3ed168508 ("Staging: add wlan-ng prism2 usb driver") Signed-off-by: Colin Ian King Cc: stable Link: https://lore.kernel.org/r/20200114181604.390235-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 7350fe5d96a3..a8860d2aee68 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -959,7 +959,7 @@ int prism2mgmt_flashdl_state(struct wlandevice *wlandev, void *msgp) } } - return 0; + return result; } /*---------------------------------------------------------------- From 01fbbd42d1f48b505714434c406f6ebbd6c9a60e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 14 Jan 2020 17:27:20 +0000 Subject: [PATCH 237/353] staging: wilc1000: remove redundant assignment to variable result The variable result is being initialized with a value that is never read and is being re-assigned later on. The assignment is redundant and hence can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200114172720.376286-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/spi.c b/drivers/staging/wilc1000/spi.c index 55f8757325f0..8694ab5fcb22 100644 --- a/drivers/staging/wilc1000/spi.c +++ b/drivers/staging/wilc1000/spi.c @@ -733,7 +733,7 @@ static int spi_internal_read(struct wilc *wilc, u32 adr, u32 *data) static int wilc_spi_write_reg(struct wilc *wilc, u32 addr, u32 data) { struct spi_device *spi = to_spi_device(wilc->dev); - int result = N_OK; + int result; u8 cmd = CMD_SINGLE_WRITE; u8 clockless = 0; @@ -782,7 +782,7 @@ static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) static int wilc_spi_read_reg(struct wilc *wilc, u32 addr, u32 *data) { struct spi_device *spi = to_spi_device(wilc->dev); - int result = N_OK; + int result; u8 cmd = CMD_SINGLE_READ; u8 clockless = 0; From 32f78c901d14bd63c38ed49d3db7d697b84e4a1c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 14 Jan 2020 17:11:45 +0000 Subject: [PATCH 238/353] staging: vt6655: remove redundant assignment to variable ret The variable ret is being initialized with a value that is never read and is being re-assigned later on. The assignment is redundant and hence can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200114171145.375356-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/rf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index fb2855e686a7..d6ca6e5551a7 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -758,7 +758,7 @@ bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, */ bool RFbSetPower(struct vnt_private *priv, unsigned int rate, u16 uCH) { - bool ret = true; + bool ret; unsigned char byPwr = 0; unsigned char byDec = 0; From 7a176c1079427194084eb169c554f0782ce6f0b4 Mon Sep 17 00:00:00 2001 From: Paulo Miguel Almeida Date: Wed, 15 Jan 2020 23:12:08 +1300 Subject: [PATCH 239/353] staging: rtl8192u: replace printk with natdev_ statements in ieee80211 Checkpatch reports 'WARNING: printk() should include KERN_ facility level'. Fix this by specifying a relevant KERN_ value for each line in which it was missing. Once they are fixed, checkpatch reports 'WARNING: Prefer [subsystem eg: netdev]_dbg([subsystem]dev, ... then dev_dbg(dev, ... then pr_debug(... to printk(KERN_DEBUG ...'. Fix this by replacing relevant printk_ statements with their netdev_ equivalent. Signed-off-by: Paulo Miguel Almeida Link: https://lore.kernel.org/r/20200115101208.GA683742@localhost.localdomain Signed-off-by: Greg Kroah-Hartman --- .../staging/rtl8192u/ieee80211/ieee80211_rx.c | 62 +++++++++---------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 00fea127bdc3..e101f7b13c7e 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -232,8 +232,7 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, #ifdef NOT_YET if (ieee->iw_mode == IW_MODE_MASTER) { - printk(KERN_DEBUG "%s: Master mode not yet supported.\n", - ieee->dev->name); + netdev_dbg(ieee->dev, "Master mode not yet supported.\n"); return 0; /* hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr_4addr *) @@ -261,9 +260,9 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, if (ieee->iw_mode == IW_MODE_MASTER) { if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) { - printk(KERN_DEBUG "%s: unknown management frame " + netdev_dbg(skb->dev, "unknown management frame " "(type=0x%02x, stype=0x%02x) dropped\n", - skb->dev->name, type, stype); + type, stype); return -1; } @@ -271,8 +270,8 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, return 0; } - printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame " - "received in non-Host AP mode\n", skb->dev->name); + netdev_dbg(skb->dev, "hostap_rx_frame_mgmt: management frame " + "received in non-Host AP mode\n"); return -1; #endif } @@ -349,9 +348,9 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, if (ieee->tkip_countermeasures && strcmp(crypt->ops->name, "TKIP") == 0) { if (net_ratelimit()) { - printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " + netdev_dbg(ieee->dev, "TKIP countermeasures: dropped " "received packet from %pM\n", - ieee->dev->name, hdr->addr2); + hdr->addr2); } return -1; } @@ -397,9 +396,9 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *s res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv); atomic_dec(&crypt->refcnt); if (res < 0) { - printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed" + netdev_dbg(ieee->dev, "MSDU decryption/MIC verification failed" " (SA=%pM keyidx=%d)\n", - ieee->dev->name, hdr->addr2, keyidx); + hdr->addr2, keyidx); return -1; } @@ -749,7 +748,8 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, kfree(prxbIndicateArray); } -static u8 parse_subframe(struct sk_buff *skb, +static u8 parse_subframe(struct ieee80211_device *ieee, + struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats, struct ieee80211_rxb *rxb, u8 *src, u8 *dst) { @@ -810,11 +810,11 @@ static u8 parse_subframe(struct sk_buff *skb, nSubframe_Length = (nSubframe_Length >> 8) + (nSubframe_Length << 8); if (skb->len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) { - printk("%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\ - __func__, rxb->nr_subframes); - printk("%s: A-MSDU parse error!! Subframe Length: %d\n", __func__, nSubframe_Length); - printk("nRemain_Length is %d and nSubframe_Length is : %d\n", skb->len, nSubframe_Length); - printk("The Packet SeqNum is %d\n", SeqNum); + netdev_dbg(ieee->dev, "A-MSDU parse error!! pRfd->nTotalSubframe : %d\n", + rxb->nr_subframes); + netdev_dbg(ieee->dev, "A-MSDU parse error!! Subframe Length: %d\n", nSubframe_Length); + netdev_dbg(ieee->dev, "nRemain_Length is %d and nSubframe_Length is : %d\n", skb->len, nSubframe_Length); + netdev_dbg(ieee->dev, "The Packet SeqNum is %d\n", SeqNum); return 0; } @@ -904,8 +904,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, stats = &ieee->stats; if (skb->len < 10) { - printk(KERN_INFO "%s: SKB length < 10\n", - dev->name); + netdev_info(dev, "SKB length < 10\n"); goto rx_dropped; } @@ -919,7 +918,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, if (HTCCheck(ieee, skb->data)) { if (net_ratelimit()) - printk("find HTCControl\n"); + netdev_warn(dev, "find HTCControl\n"); hdrlen += 4; rx_stats->bContainHTC = true; } @@ -1113,7 +1112,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) { - printk("decrypt frame error\n"); + netdev_dbg(ieee->dev, "decrypt frame error\n"); goto rx_dropped; } @@ -1141,9 +1140,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, flen -= hdrlen; if (frag_skb->tail + flen > frag_skb->end) { - printk(KERN_WARNING "%s: host decrypted and " - "reassembled frame did not fit skb\n", - dev->name); + netdev_warn(dev, "host decrypted and " + "reassembled frame did not fit skb\n"); ieee80211_frag_cache_invalidate(ieee, hdr); goto rx_dropped; } @@ -1178,7 +1176,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, * encrypted/authenticated */ if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) { - printk("==>decrypt msdu error\n"); + netdev_dbg(ieee->dev, "==>decrypt msdu error\n"); goto rx_dropped; } @@ -1250,7 +1248,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, goto rx_dropped; /* to parse amsdu packets */ /* qos data packets & reserved bit is 1 */ - if (parse_subframe(skb, rx_stats, rxb, src, dst) == 0) { + if (parse_subframe(ieee, skb, rx_stats, rxb, src, dst) == 0) { /* only to free rxb, and not submit the packets to upper layer */ for (i = 0; i < rxb->nr_subframes; i++) { dev_kfree_skb(rxb->subframes[i]); @@ -1863,7 +1861,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[0] == 0x00 && info_element->data[1] == 0x13 && info_element->data[2] == 0x74)) { - printk("========>%s(): athros AP is exist\n", __func__); + netdev_dbg(ieee->dev, "========> athros AP is exist\n"); network->atheros_cap_exist = true; } else network->atheros_cap_exist = false; @@ -1980,8 +1978,8 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, } break; case MFIE_TYPE_QOS_PARAMETER: - printk(KERN_ERR - "QoS Error need to parse QOS_PARAMETER IE\n"); + netdev_err(ieee->dev, + "QoS Error need to parse QOS_PARAMETER IE\n"); break; case MFIE_TYPE_COUNTRY: @@ -2357,14 +2355,14 @@ static inline void ieee80211_process_probe_response( if (IS_COUNTRY_IE_VALID(ieee)) { // Case 1: Country code if (!is_legal_channel(ieee, network->channel)) { - printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network->channel); + netdev_warn(ieee->dev, "GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network->channel); goto out; } } else { // Case 2: No any country code. // Filter over channel ch12~14 if (network->channel > 11) { - printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network->channel); + netdev_warn(ieee->dev, "GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network->channel); goto out; } } @@ -2372,14 +2370,14 @@ static inline void ieee80211_process_probe_response( if (IS_COUNTRY_IE_VALID(ieee)) { // Case 1: Country code if (!is_legal_channel(ieee, network->channel)) { - printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n", network->channel); + netdev_warn(ieee->dev, "GetScanInfo(): For Country code, filter beacon at channel(%d).\n", network->channel); goto out; } } else { // Case 2: No any country code. // Filter over channel ch12~14 if (network->channel > 14) { - printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n", network->channel); + netdev_warn(ieee->dev, "GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n", network->channel); goto out; } } From ca78e042f286af6d8171481e4ec6800f3843b89f Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 14 Jan 2020 16:57:50 +0100 Subject: [PATCH 240/353] staging: most: core: fix date in file comment This patch updates the date range in the comment section. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1579017478-3339-2-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index af542ed6c7f0..bc375e73a9d1 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -2,7 +2,7 @@ /* * core.c - Implementation of core module of MOST Linux driver stack * - * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG + * Copyright (C) 2013-2020 Microchip Technology Germany II GmbH & Co. KG */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt From 78ce8b26e3cfef58475a7caa6c83392ff276674f Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 14 Jan 2020 16:57:51 +0100 Subject: [PATCH 241/353] staging: most: core: use dev_* function for logging This patch replaces all calls to pr_* functions and uses the dev_* functions instead. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1579017478-3339-3-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 61 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index bc375e73a9d1..be9efa88693c 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -5,7 +5,6 @@ * Copyright (C) 2013-2020 Microchip Technology Germany II GmbH & Co. KG */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include #include @@ -151,7 +150,7 @@ static void flush_channel_fifos(struct most_channel *c) spin_unlock_irqrestore(&c->fifo_lock, hf_flags); if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo)))) - pr_info("WARN: fifo | trash fifo not empty\n"); + dev_warn(&mc.dev, "fifo | trash fifo not empty\n"); } /** @@ -623,7 +622,7 @@ int most_set_cfg_datatype(char *mdev, char *mdev_ch, char *buf) } if (i == ARRAY_SIZE(ch_data_type)) - pr_info("WARN: invalid attribute settings\n"); + dev_warn(&mc.dev, "invalid attribute settings\n"); return 0; } @@ -642,7 +641,7 @@ int most_set_cfg_direction(char *mdev, char *mdev_ch, char *buf) } else if (!strcmp(buf, "tx")) { c->cfg.direction = MOST_CH_TX; } else { - pr_info("Invalid direction\n"); + dev_err(&mc.dev, "Invalid direction\n"); return -ENODATA; } return 0; @@ -795,7 +794,7 @@ static int hdm_enqueue_thread(void *data) mutex_unlock(&c->nq_mutex); if (unlikely(ret)) { - pr_err("hdm enqueue failed\n"); + dev_err(&mc.dev, "hdm enqueue failed\n"); nq_hdm_mbo(mbo); c->hdm_enqueue_task = NULL; return 0; @@ -942,7 +941,7 @@ static void most_write_completion(struct mbo *mbo) c = mbo->context; if (mbo->status == MBO_E_INVAL) - pr_info("WARN: Tx MBO status: invalid\n"); + dev_warn(&mc.dev, "Tx MBO status: invalid\n"); if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) trash_mbo(mbo); else @@ -1101,14 +1100,14 @@ int most_start_channel(struct most_interface *iface, int id, goto out; /* already started by another component */ if (!try_module_get(iface->mod)) { - pr_info("failed to acquire HDM lock\n"); + dev_err(&mc.dev, "failed to acquire HDM lock\n"); mutex_unlock(&c->start_mutex); return -ENOLCK; } c->cfg.extra_len = 0; if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) { - pr_info("channel configuration failed. Go check settings...\n"); + dev_err(&mc.dev, "channel configuration failed. Go check settings...\n"); ret = -EINVAL; goto err_put_module; } @@ -1162,7 +1161,7 @@ int most_stop_channel(struct most_interface *iface, int id, struct most_channel *c; if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) { - pr_err("Bad interface or index out of range\n"); + dev_err(&mc.dev, "Bad interface or index out of range\n"); return -EINVAL; } c = iface->p->channel[id]; @@ -1182,8 +1181,8 @@ int most_stop_channel(struct most_interface *iface, int id, c->is_poisoned = true; if (c->iface->poison_channel(c->iface, c->channel_id)) { - pr_err("Cannot stop channel %d of mdev %s\n", c->channel_id, - c->iface->description); + dev_err(&mc.dev, "Cannot stop channel %d of mdev %s\n", c->channel_id, + c->iface->description); mutex_unlock(&c->start_mutex); return -EAGAIN; } @@ -1192,7 +1191,7 @@ int most_stop_channel(struct most_interface *iface, int id, #ifdef CMPL_INTERRUPTIBLE if (wait_for_completion_interruptible(&c->cleanup)) { - pr_info("Interrupted while clean up ch %d\n", c->channel_id); + dev_err(&mc.dev, "Interrupted while clean up ch %d\n", c->channel_id); mutex_unlock(&c->start_mutex); return -EINTR; } @@ -1218,11 +1217,11 @@ EXPORT_SYMBOL_GPL(most_stop_channel); int most_register_component(struct most_component *comp) { if (!comp) { - pr_err("Bad component\n"); + dev_err(&mc.dev, "Bad component\n"); return -EINVAL; } list_add_tail(&comp->list, &mc.comp_list); - pr_info("registered new core component %s\n", comp->name); + dev_info(&mc.dev, "registered new core component %s\n", comp->name); return 0; } EXPORT_SYMBOL_GPL(most_register_component); @@ -1252,25 +1251,25 @@ static int disconnect_channels(struct device *dev, void *data) int most_deregister_component(struct most_component *comp) { if (!comp) { - pr_err("Bad component\n"); + dev_err(&mc.dev, "Bad component\n"); return -EINVAL; } bus_for_each_dev(&mc.bus, NULL, comp, disconnect_channels); list_del(&comp->list); - pr_info("deregistering component %s\n", comp->name); + dev_info(&mc.dev, "deregistering component %s\n", comp->name); return 0; } EXPORT_SYMBOL_GPL(most_deregister_component); static void release_interface(struct device *dev) { - pr_info("releasing interface dev %s...\n", dev_name(dev)); + dev_info(&mc.dev, "releasing interface dev %s...\n", dev_name(dev)); } static void release_channel(struct device *dev) { - pr_info("releasing channel dev %s...\n", dev_name(dev)); + dev_info(&mc.dev, "releasing channel dev %s...\n", dev_name(dev)); } /** @@ -1288,13 +1287,13 @@ int most_register_interface(struct most_interface *iface) if (!iface || !iface->enqueue || !iface->configure || !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) { - pr_err("Bad interface or channel overflow\n"); + dev_err(&mc.dev, "Bad interface or channel overflow\n"); return -EINVAL; } id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL); if (id < 0) { - pr_info("Failed to alloc mdev ID\n"); + dev_err(&mc.dev, "Failed to alloc mdev ID\n"); return id; } @@ -1313,7 +1312,7 @@ int most_register_interface(struct most_interface *iface) iface->dev.groups = interface_attr_groups; iface->dev.release = release_interface; if (device_register(&iface->dev)) { - pr_err("registering iface->dev failed\n"); + dev_err(&mc.dev, "registering iface->dev failed\n"); kfree(iface->p); ida_simple_remove(&mdev_id, id); return -ENOMEM; @@ -1356,12 +1355,12 @@ int most_register_interface(struct most_interface *iface) mutex_init(&c->nq_mutex); list_add_tail(&c->list, &iface->p->channel_list); if (device_register(&c->dev)) { - pr_err("registering c->dev failed\n"); + dev_err(&mc.dev, "registering c->dev failed\n"); goto err_free_most_channel; } } - pr_info("registered new device mdev%d (%s)\n", - id, iface->description); + dev_info(&mc.dev, "registered new device mdev%d (%s)\n", + id, iface->description); most_interface_register_notify(iface->description); return 0; @@ -1393,8 +1392,8 @@ void most_deregister_interface(struct most_interface *iface) int i; struct most_channel *c; - pr_info("deregistering device %s (%s)\n", dev_name(&iface->dev), - iface->description); + dev_info(&mc.dev, "deregistering device %s (%s)\n", dev_name(&iface->dev), + iface->description); for (i = 0; i < iface->num_channels; i++) { c = iface->p->channel[i]; if (c->pipe0.comp) @@ -1464,14 +1463,14 @@ EXPORT_SYMBOL_GPL(most_resume_enqueue); static void release_most_sub(struct device *dev) { - pr_info("releasing most_subsystem\n"); + dev_info(&mc.dev, "releasing most_subsystem\n"); } static int __init most_init(void) { int err; - pr_info("init()\n"); + dev_info(&mc.dev, "init()\n"); INIT_LIST_HEAD(&mc.comp_list); ida_init(&mdev_id); @@ -1483,12 +1482,12 @@ static int __init most_init(void) err = bus_register(&mc.bus); if (err) { - pr_info("Cannot register most bus\n"); + dev_err(&mc.dev, "Cannot register most bus\n"); return err; } err = driver_register(&mc.drv); if (err) { - pr_info("Cannot register core driver\n"); + dev_err(&mc.dev, "Cannot register core driver\n"); goto err_unregister_bus; } mc.dev.init_name = "most_bus"; @@ -1509,7 +1508,7 @@ err_unregister_bus: static void __exit most_exit(void) { - pr_info("exit core module\n"); + dev_info(&mc.dev, "exit core module\n"); device_unregister(&mc.dev); driver_unregister(&mc.drv); bus_unregister(&mc.bus); From 793769120b109e3cec536bb8f5b6f9ef959c315f Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 14 Jan 2020 16:57:52 +0100 Subject: [PATCH 242/353] staging: most: core: remove noisy log messages In order to not generate unnecessary noise in the kernel log,this patch removes debug log messages. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1579017478-3339-4-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index be9efa88693c..5772f893c2b5 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -1221,7 +1221,6 @@ int most_register_component(struct most_component *comp) return -EINVAL; } list_add_tail(&comp->list, &mc.comp_list); - dev_info(&mc.dev, "registered new core component %s\n", comp->name); return 0; } EXPORT_SYMBOL_GPL(most_register_component); @@ -1257,7 +1256,6 @@ int most_deregister_component(struct most_component *comp) bus_for_each_dev(&mc.bus, NULL, comp, disconnect_channels); list_del(&comp->list); - dev_info(&mc.dev, "deregistering component %s\n", comp->name); return 0; } EXPORT_SYMBOL_GPL(most_deregister_component); @@ -1359,8 +1357,6 @@ int most_register_interface(struct most_interface *iface) goto err_free_most_channel; } } - dev_info(&mc.dev, "registered new device mdev%d (%s)\n", - id, iface->description); most_interface_register_notify(iface->description); return 0; @@ -1392,8 +1388,6 @@ void most_deregister_interface(struct most_interface *iface) int i; struct most_channel *c; - dev_info(&mc.dev, "deregistering device %s (%s)\n", dev_name(&iface->dev), - iface->description); for (i = 0; i < iface->num_channels; i++) { c = iface->p->channel[i]; if (c->pipe0.comp) @@ -1470,7 +1464,6 @@ static int __init most_init(void) { int err; - dev_info(&mc.dev, "init()\n"); INIT_LIST_HEAD(&mc.comp_list); ida_init(&mdev_id); @@ -1508,7 +1501,6 @@ err_unregister_bus: static void __exit most_exit(void) { - dev_info(&mc.dev, "exit core module\n"); device_unregister(&mc.dev); driver_unregister(&mc.drv); bus_unregister(&mc.bus); From 532c29190795178bb02d2671b5e8a288c16a4649 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 16 Jan 2020 01:44:51 +0900 Subject: [PATCH 243/353] staging: most: remove header include path to drivers/staging There is no need to add "ccflags-y += -I $(srctree)/drivers/staging" just for including . Use the #include "..." directive with the correct relative path. Signed-off-by: Masahiro Yamada Link: https://lore.kernel.org/r/20200115164451.13203-1-masahiroy@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/Makefile | 1 - drivers/staging/most/cdev/Makefile | 1 - drivers/staging/most/cdev/cdev.c | 3 ++- drivers/staging/most/configfs.c | 3 ++- drivers/staging/most/core.c | 3 ++- drivers/staging/most/dim2/Makefile | 1 - drivers/staging/most/dim2/dim2.c | 2 +- drivers/staging/most/i2c/Makefile | 1 - drivers/staging/most/i2c/i2c.c | 2 +- drivers/staging/most/net/Makefile | 1 - drivers/staging/most/net/net.c | 3 ++- drivers/staging/most/sound/Makefile | 1 - drivers/staging/most/sound/sound.c | 3 ++- drivers/staging/most/usb/Makefile | 1 - drivers/staging/most/usb/usb.c | 3 ++- drivers/staging/most/video/Makefile | 1 - drivers/staging/most/video/video.c | 2 +- 17 files changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/staging/most/Makefile b/drivers/staging/most/Makefile index 85ea5a434ced..20a99ecb37c4 100644 --- a/drivers/staging/most/Makefile +++ b/drivers/staging/most/Makefile @@ -2,7 +2,6 @@ obj-$(CONFIG_MOST) += most_core.o most_core-y := core.o most_core-y += configfs.o -ccflags-y += -I $(srctree)/drivers/staging/ obj-$(CONFIG_MOST_CDEV) += cdev/ obj-$(CONFIG_MOST_NET) += net/ diff --git a/drivers/staging/most/cdev/Makefile b/drivers/staging/most/cdev/Makefile index 9f4a8b8c9c27..ef90cd71994a 100644 --- a/drivers/staging/most/cdev/Makefile +++ b/drivers/staging/most/cdev/Makefile @@ -2,4 +2,3 @@ obj-$(CONFIG_MOST_CDEV) += most_cdev.o most_cdev-objs := cdev.o -ccflags-y += -I $(srctree)/drivers/staging/ diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index 59f346d1f4af..71943d17f825 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -16,7 +16,8 @@ #include #include #include -#include + +#include "../most.h" #define CHRDEV_REGION_SIZE 50 diff --git a/drivers/staging/most/configfs.c b/drivers/staging/most/configfs.c index 9818f6c8b22a..034ab96ef69e 100644 --- a/drivers/staging/most/configfs.c +++ b/drivers/staging/most/configfs.c @@ -10,7 +10,8 @@ #include #include #include -#include + +#include "most.h" #define MAX_STRING_SIZE 80 diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 5772f893c2b5..bcad2525d94b 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -20,7 +20,8 @@ #include #include #include -#include + +#include "most.h" #define MAX_CHANNELS 64 #define STRING_SIZE 80 diff --git a/drivers/staging/most/dim2/Makefile b/drivers/staging/most/dim2/Makefile index 116f04d69244..861adacf6c72 100644 --- a/drivers/staging/most/dim2/Makefile +++ b/drivers/staging/most/dim2/Makefile @@ -2,4 +2,3 @@ obj-$(CONFIG_MOST_DIM2) += most_dim2.o most_dim2-objs := dim2.o hal.o sysfs.o -ccflags-y += -I $(srctree)/drivers/staging/ diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index 9eb10fc0903e..15c6aa8fa1ea 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -21,7 +21,7 @@ #include #include -#include +#include "../most.h" #include "hal.h" #include "errors.h" #include "sysfs.h" diff --git a/drivers/staging/most/i2c/Makefile b/drivers/staging/most/i2c/Makefile index 2b3769dc19e7..71099dd0f85b 100644 --- a/drivers/staging/most/i2c/Makefile +++ b/drivers/staging/most/i2c/Makefile @@ -2,4 +2,3 @@ obj-$(CONFIG_MOST_I2C) += most_i2c.o most_i2c-objs := i2c.o -ccflags-y += -I $(srctree)/drivers/staging/ diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c index d07719c38fc9..2980f7065846 100644 --- a/drivers/staging/most/i2c/i2c.c +++ b/drivers/staging/most/i2c/i2c.c @@ -14,7 +14,7 @@ #include #include -#include +#include "../most.h" enum { CH_RX, CH_TX, NUM_CHANNELS }; diff --git a/drivers/staging/most/net/Makefile b/drivers/staging/most/net/Makefile index f0ac64dee71b..1582c97eb204 100644 --- a/drivers/staging/most/net/Makefile +++ b/drivers/staging/most/net/Makefile @@ -2,4 +2,3 @@ obj-$(CONFIG_MOST_NET) += most_net.o most_net-objs := net.o -ccflags-y += -I $(srctree)/drivers/staging/ diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index db4273256ce8..8218c9a06cb5 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -15,7 +15,8 @@ #include #include #include -#include + +#include "../most.h" #define MEP_HDR_LEN 8 #define MDP_HDR_LEN 16 diff --git a/drivers/staging/most/sound/Makefile b/drivers/staging/most/sound/Makefile index a3d086c6ca70..f0cd9d8d213e 100644 --- a/drivers/staging/most/sound/Makefile +++ b/drivers/staging/most/sound/Makefile @@ -2,4 +2,3 @@ obj-$(CONFIG_MOST_SOUND) += most_sound.o most_sound-objs := sound.o -ccflags-y += -I $(srctree)/drivers/staging/ diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 23baf4bd7c12..44cf2334834f 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -17,7 +17,8 @@ #include #include #include -#include + +#include "../most.h" #define DRIVER_NAME "sound" #define STRING_SIZE 80 diff --git a/drivers/staging/most/usb/Makefile b/drivers/staging/most/usb/Makefile index 83cf2ead7122..c2b207339aec 100644 --- a/drivers/staging/most/usb/Makefile +++ b/drivers/staging/most/usb/Makefile @@ -2,4 +2,3 @@ obj-$(CONFIG_MOST_USB) += most_usb.o most_usb-objs := usb.o -ccflags-y += -I $(srctree)/drivers/staging/ diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c index 491b38e91e9d..35217ca65cbb 100644 --- a/drivers/staging/most/usb/usb.c +++ b/drivers/staging/most/usb/usb.c @@ -23,7 +23,8 @@ #include #include #include -#include + +#include "../most.h" #define USB_MTU 512 #define NO_ISOCHRONOUS_URB 0 diff --git a/drivers/staging/most/video/Makefile b/drivers/staging/most/video/Makefile index 2d857d3cbcc8..856175fec8b6 100644 --- a/drivers/staging/most/video/Makefile +++ b/drivers/staging/most/video/Makefile @@ -2,4 +2,3 @@ obj-$(CONFIG_MOST_VIDEO) += most_video.o most_video-objs := video.o -ccflags-y += -I $(srctree)/drivers/staging/ diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index 9e9e45ac386e..d32ae49d617b 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -21,7 +21,7 @@ #include #include -#include +#include "../most.h" #define V4L2_CMP_MAX_INPUT 1 From 8b08b6a8c31f18c3657405410e4c3f6bc4fa75f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:03 +0000 Subject: [PATCH 244/353] staging: wfx: revert unexpected change in debugfs output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It appears that commit 8c7128c4cf4e ("staging: align to fix warnings of line over 80 characters") do slightly more than what is explained in commit log. Especially, it changes the output of the file rx_stats from debugfs. From some point of view, this file can be considered as a part of the API. Any change on it should be clearly announced. Since the change introduced does not seems to have any justification, revert it. Reported-by: Pascal Prime Cc: Jules Irenge Fixes: 8c7128c4cf4e ("staging: align to fix warnings of line over 80 characters") Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-2-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wfx/debug.c b/drivers/staging/wfx/debug.c index d17a75242365..1164aba118a1 100644 --- a/drivers/staging/wfx/debug.c +++ b/drivers/staging/wfx/debug.c @@ -145,7 +145,7 @@ static int wfx_rx_stats_show(struct seq_file *seq, void *v) st->pwr_clk_freq, st->is_ext_pwr_clk ? "yes" : "no"); seq_printf(seq, - "N. of frames: %d, PER (x10e4): %d, Throughput: %dKbps/s\n", + "Num. of frames: %d, PER (x10e4): %d, Throughput: %dKbps/s\n", st->nb_rx_frame, st->per_total, st->throughput); seq_puts(seq, " Num. of PER RSSI SNR CFO\n"); seq_puts(seq, " frames (x10e4) (dBm) (dB) (kHz)\n"); From 99aa34a62bce1366aa0b856ba9262e19072a1faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:05 +0000 Subject: [PATCH 245/353] staging: wfx: make hif_scan() usage clearer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hif_scan() return max number of jiffies to wait before the completion indication. However, if this value is negative, an error has occurred. Reword the code to reflect that behavior. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-3-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/scan.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index 24061d09c404..9b3674b3226a 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -56,10 +56,9 @@ static int send_scan_req(struct wfx_vif *wvif, wfx_tx_lock_flush(wvif->wdev); wvif->scan_abort = false; reinit_completion(&wvif->scan_complete); - ret = hif_scan(wvif, req, start_idx, i - start_idx); - if (ret < 0) - return ret; - timeout = ret; + timeout = hif_scan(wvif, req, start_idx, i - start_idx); + if (timeout < 0) + return timeout; ret = wait_for_completion_timeout(&wvif->scan_complete, timeout); if (req->channels[start_idx]->max_power != wvif->wdev->output_power) hif_set_output_power(wvif, wvif->wdev->output_power * 10); From 1e30e3c5a4c0781e10e2d6d7753e7da459b118f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:06 +0000 Subject: [PATCH 246/353] staging: wfx: add missing PROBE_RESP_OFFLOAD feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some userspace tools (hostapd) rely on probe_resp_offload fields for certain features. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-4-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c index 45c9939b7e62..1904890c03fe 100644 --- a/drivers/staging/wfx/main.c +++ b/drivers/staging/wfx/main.c @@ -298,6 +298,11 @@ struct wfx_dev *wfx_init_common(struct device *dev, hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); + hw->wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; + hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; hw->wiphy->max_ap_assoc_sta = WFX_MAX_STA_IN_AP_MODE; From 9ab564653abb9dade6ca8530a3e3a2f622dcd7f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:07 +0000 Subject: [PATCH 247/353] staging: wfx: send rate policies one by one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rate policies (aka. tx_rate_retry_policy in hardware API) are sent to device asynchronously from tx requests. So, the device maintains a list of active rate policies and the tx requests only reference an existent rate policy. The device API allows to send multiple rate policies at once. However, this property is very rarely used. We prefer to send rate policies one by one and simplify the architecture. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-5-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 53 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index b2a325c47b2d..fb51c5910ace 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -217,37 +217,34 @@ static void wfx_tx_policy_put(struct wfx_vif *wvif, int idx) static int wfx_tx_policy_upload(struct wfx_vif *wvif) { - int i; - struct tx_policy_cache *cache = &wvif->tx_policy_cache; struct hif_mib_set_tx_rate_retry_policy *arg = - kzalloc(struct_size(arg, - tx_rate_retry_policy, - HIF_MIB_NUM_TX_RATE_RETRY_POLICIES), - GFP_KERNEL); - struct hif_mib_tx_rate_retry_policy *dst; + kzalloc(struct_size(arg, tx_rate_retry_policy, 1), GFP_KERNEL); + struct tx_policy *policies = wvif->tx_policy_cache.cache; + int i; - spin_lock_bh(&cache->lock); - /* Upload only modified entries. */ - for (i = 0; i < HIF_MIB_NUM_TX_RATE_RETRY_POLICIES; ++i) { - struct tx_policy *src = &cache->cache[i]; - - if (!src->uploaded && memzcmp(src->rates, sizeof(src->rates))) { - dst = arg->tx_rate_retry_policy + - arg->num_tx_rate_policies; - - dst->policy_index = i; - dst->short_retry_count = 255; - dst->long_retry_count = 255; - dst->first_rate_sel = 1; - dst->terminate = 1; - dst->count_init = 1; - memcpy(&dst->rates, src->rates, sizeof(src->rates)); - src->uploaded = true; - arg->num_tx_rate_policies++; + do { + spin_lock_bh(&wvif->tx_policy_cache.lock); + for (i = 0; i < HIF_MIB_NUM_TX_RATE_RETRY_POLICIES; ++i) + if (!policies[i].uploaded && + memzcmp(policies[i].rates, sizeof(policies[i].rates))) + break; + if (i < HIF_MIB_NUM_TX_RATE_RETRY_POLICIES) { + policies[i].uploaded = 1; + arg->num_tx_rate_policies = 1; + arg->tx_rate_retry_policy[0].policy_index = i; + arg->tx_rate_retry_policy[0].short_retry_count = 255; + arg->tx_rate_retry_policy[0].long_retry_count = 255; + arg->tx_rate_retry_policy[0].first_rate_sel = 1; + arg->tx_rate_retry_policy[0].terminate = 1; + arg->tx_rate_retry_policy[0].count_init = 1; + memcpy(&arg->tx_rate_retry_policy[0].rates, + policies[i].rates, sizeof(policies[i].rates)); + spin_unlock_bh(&wvif->tx_policy_cache.lock); + hif_set_tx_rate_retry_policy(wvif, arg); + } else { + spin_unlock_bh(&wvif->tx_policy_cache.lock); } - } - spin_unlock_bh(&cache->lock); - hif_set_tx_rate_retry_policy(wvif, arg); + } while (i < HIF_MIB_NUM_TX_RATE_RETRY_POLICIES); kfree(arg); return 0; } From c360f1ccdcf9532a8d8cee0f0976b28b6cb4e35b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:09 +0000 Subject: [PATCH 248/353] staging: wfx: simplify hif_set_tx_rate_retry_policy() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structure hif_mib_set_tx_rate_retry_policy come from hardware API. It is not intended to be manipulated in upper layers of the driver. So, this patch relocate handling of this structure to hif_set_tx_rate_retry_policy() (the low level function). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-6-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 16 +++------------- drivers/staging/wfx/hif_tx_mib.h | 23 ++++++++++++++++++----- drivers/staging/wfx/sta.c | 2 +- drivers/staging/wfx/sta.h | 1 + 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index fb51c5910ace..60459299a3a9 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -217,9 +217,8 @@ static void wfx_tx_policy_put(struct wfx_vif *wvif, int idx) static int wfx_tx_policy_upload(struct wfx_vif *wvif) { - struct hif_mib_set_tx_rate_retry_policy *arg = - kzalloc(struct_size(arg, tx_rate_retry_policy, 1), GFP_KERNEL); struct tx_policy *policies = wvif->tx_policy_cache.cache; + u8 tmp_rates[12]; int i; do { @@ -230,22 +229,13 @@ static int wfx_tx_policy_upload(struct wfx_vif *wvif) break; if (i < HIF_MIB_NUM_TX_RATE_RETRY_POLICIES) { policies[i].uploaded = 1; - arg->num_tx_rate_policies = 1; - arg->tx_rate_retry_policy[0].policy_index = i; - arg->tx_rate_retry_policy[0].short_retry_count = 255; - arg->tx_rate_retry_policy[0].long_retry_count = 255; - arg->tx_rate_retry_policy[0].first_rate_sel = 1; - arg->tx_rate_retry_policy[0].terminate = 1; - arg->tx_rate_retry_policy[0].count_init = 1; - memcpy(&arg->tx_rate_retry_policy[0].rates, - policies[i].rates, sizeof(policies[i].rates)); + memcpy(tmp_rates, policies[i].rates, sizeof(tmp_rates)); spin_unlock_bh(&wvif->tx_policy_cache.lock); - hif_set_tx_rate_retry_policy(wvif, arg); + hif_set_tx_rate_retry_policy(wvif, i, tmp_rates); } else { spin_unlock_bh(&wvif->tx_policy_cache.lock); } } while (i < HIF_MIB_NUM_TX_RATE_RETRY_POLICIES); - kfree(arg); return 0; } diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index b1eeda2a3ab3..ef033a409381 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -181,13 +181,26 @@ static inline int hif_set_association_mode(struct wfx_vif *wvif, } static inline int hif_set_tx_rate_retry_policy(struct wfx_vif *wvif, - struct hif_mib_set_tx_rate_retry_policy *arg) + int policy_index, uint8_t *rates) { - size_t size = struct_size(arg, tx_rate_retry_policy, - arg->num_tx_rate_policies); + struct hif_mib_set_tx_rate_retry_policy *arg; + size_t size = struct_size(arg, tx_rate_retry_policy, 1); + int ret; - return hif_write_mib(wvif->wdev, wvif->id, - HIF_MIB_ID_SET_TX_RATE_RETRY_POLICY, arg, size); + arg = kzalloc(size, GFP_KERNEL); + arg->num_tx_rate_policies = 1; + arg->tx_rate_retry_policy[0].policy_index = policy_index; + arg->tx_rate_retry_policy[0].short_retry_count = 255; + arg->tx_rate_retry_policy[0].long_retry_count = 255; + arg->tx_rate_retry_policy[0].first_rate_sel = 1; + arg->tx_rate_retry_policy[0].terminate = 1; + arg->tx_rate_retry_policy[0].count_init = 1; + memcpy(&arg->tx_rate_retry_policy[0].rates, rates, + sizeof(arg->tx_rate_retry_policy[0].rates)); + ret = hif_write_mib(wvif->wdev, wvif->id, + HIF_MIB_ID_SET_TX_RATE_RETRY_POLICY, arg, size); + kfree(arg); + return ret; } static inline int hif_set_mac_addr_condition(struct wfx_vif *wvif, diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 9011b5d78706..8f53a78d7215 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -19,7 +19,7 @@ #define HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES 2 -static u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates) +u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates) { int i; u32 ret = 0; diff --git a/drivers/staging/wfx/sta.h b/drivers/staging/wfx/sta.h index 9595e1fc60db..b5d8d6494157 100644 --- a/drivers/staging/wfx/sta.h +++ b/drivers/staging/wfx/sta.h @@ -92,5 +92,6 @@ void wfx_suspend_resume(struct wfx_vif *wvif, void wfx_cqm_bssloss_sm(struct wfx_vif *wvif, int init, int good, int bad); void wfx_update_filtering(struct wfx_vif *wvif); int wfx_fwd_probe_req(struct wfx_vif *wvif, bool enable); +u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates); #endif /* WFX_STA_H */ From 5fd64673cf6e2ca08447a77de3d2fe7e73d54915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:10 +0000 Subject: [PATCH 249/353] staging: wfx: simplify hif_set_output_power() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardware API use 10th of dBm for output power unit. Upper layers should use same units than mac80211 and the conversion should be done by low level layer of the driver (hif_set_output_power()) In add, current code of hif_set_output_power() use a __le32 while the device API specify a specific structure for this. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-7-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx_mib.h | 8 +++++--- drivers/staging/wfx/scan.c | 2 +- drivers/staging/wfx/sta.c | 6 +++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index ef033a409381..749df67131c3 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -15,13 +15,15 @@ #include "hif_tx.h" #include "hif_api_mib.h" -static inline int hif_set_output_power(struct wfx_vif *wvif, int power_level) +static inline int hif_set_output_power(struct wfx_vif *wvif, int val) { - __le32 val = cpu_to_le32(power_level); + struct hif_mib_current_tx_power_level arg = { + .power_level = cpu_to_le32(val * 10), + }; return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_CURRENT_TX_POWER_LEVEL, - &val, sizeof(val)); + &arg, sizeof(arg)); } static inline int hif_set_beacon_wakeup_period(struct wfx_vif *wvif, diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index 9b3674b3226a..8e0ac89fd28f 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -61,7 +61,7 @@ static int send_scan_req(struct wfx_vif *wvif, return timeout; ret = wait_for_completion_timeout(&wvif->scan_complete, timeout); if (req->channels[start_idx]->max_power != wvif->wdev->output_power) - hif_set_output_power(wvif, wvif->wdev->output_power * 10); + hif_set_output_power(wvif, wvif->wdev->output_power); wfx_tx_unlock(wvif->wdev); if (!ret) { dev_notice(wvif->wdev->dev, "scan timeout\n"); diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 8f53a78d7215..11e33a6d5bb5 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -503,7 +503,7 @@ static void wfx_do_unjoin(struct wfx_vif *wvif) hif_keep_alive_period(wvif, 0); hif_reset(wvif, false); wfx_tx_policy_init(wvif); - hif_set_output_power(wvif, wvif->wdev->output_power * 10); + hif_set_output_power(wvif, wvif->wdev->output_power); wvif->dtim_period = 0; hif_set_macaddr(wvif, wvif->vif->addr); wfx_free_event_queue(wvif); @@ -1063,7 +1063,7 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_TXPOWER && info->txpower != wdev->output_power) { wdev->output_power = info->txpower; - hif_set_output_power(wvif, wdev->output_power * 10); + hif_set_output_power(wvif, wdev->output_power); } mutex_unlock(&wdev->conf_mutex); @@ -1317,7 +1317,7 @@ int wfx_config(struct ieee80211_hw *hw, u32 changed) mutex_lock(&wdev->conf_mutex); if (changed & IEEE80211_CONF_CHANGE_POWER) { wdev->output_power = conf->power_level; - hif_set_output_power(wvif, wdev->output_power * 10); + hif_set_output_power(wvif, wdev->output_power); } if (changed & IEEE80211_CONF_CHANGE_PS) { From 9ed8b0d0f27cf7ba183d8e8e7c5cc47afb7a00ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:12 +0000 Subject: [PATCH 250/353] staging: wfx: simplify hif_set_rcpi_rssi_threshold() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structure hif_mib_rcpi_rssi_threshold come from hardware API. It is not intended to be manipulated in upper layers of the driver. In add, current code for hif_set_rcpi_rssi_threshold() is dumb. It should pack data using the hardware representation instead of leaving all work to the caller. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-8-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx_mib.h | 19 +++++++++++++++++-- drivers/staging/wfx/sta.c | 26 ++------------------------ 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index 749df67131c3..a8082508fbfd 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -44,10 +44,25 @@ static inline int hif_set_beacon_wakeup_period(struct wfx_vif *wvif, } static inline int hif_set_rcpi_rssi_threshold(struct wfx_vif *wvif, - struct hif_mib_rcpi_rssi_threshold *arg) + int rssi_thold, int rssi_hyst) { + struct hif_mib_rcpi_rssi_threshold arg = { + .rolling_average_count = 8, + .detection = 1, + }; + + if (!rssi_thold && !rssi_hyst) { + arg.upperthresh = 1; + arg.lowerthresh = 1; + } else { + arg.upper_threshold = rssi_thold + rssi_hyst; + arg.upper_threshold = (arg.upper_threshold + 110) * 2; + arg.lower_threshold = rssi_thold; + arg.lower_threshold = (arg.lower_threshold + 110) * 2; + } + return hif_write_mib(wvif->wdev, wvif->id, - HIF_MIB_ID_RCPI_RSSI_THRESHOLD, arg, sizeof(*arg)); + HIF_MIB_ID_RCPI_RSSI_THRESHOLD, &arg, sizeof(arg)); } static inline int hif_get_counters_table(struct wfx_dev *wdev, diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 11e33a6d5bb5..339acbce96fb 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -1033,31 +1033,9 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, hif_slot_time(wvif, info->use_short_slot ? 9 : 20); if (changed & BSS_CHANGED_ASSOC || changed & BSS_CHANGED_CQM) { - struct hif_mib_rcpi_rssi_threshold th = { - .rolling_average_count = 8, - .detection = 1, - }; - wvif->cqm_rssi_thold = info->cqm_rssi_thold; - - if (!info->cqm_rssi_thold && !info->cqm_rssi_hyst) { - th.upperthresh = 1; - th.lowerthresh = 1; - } else { - /* FIXME It's not a correct way of setting threshold. - * Upper and lower must be set equal here and adjusted - * in callback. However current implementation is much - * more reliable and stable. - */ - /* RSSI: signed Q8.0, RCPI: unsigned Q7.1 - * RSSI = RCPI / 2 - 110 - */ - th.upper_threshold = info->cqm_rssi_thold + info->cqm_rssi_hyst; - th.upper_threshold = (th.upper_threshold + 110) * 2; - th.lower_threshold = info->cqm_rssi_thold; - th.lower_threshold = (th.lower_threshold + 110) * 2; - } - hif_set_rcpi_rssi_threshold(wvif, &th); + hif_set_rcpi_rssi_threshold(wvif, info->cqm_rssi_thold, + info->cqm_rssi_hyst); } if (changed & BSS_CHANGED_TXPOWER && From e52e68eee7d0a6731d2f8d9234ba3ab226f392dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:13 +0000 Subject: [PATCH 251/353] staging: wfx: simplify hif_set_arp_ipv4_filter() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structure hif_mib_arp_ip_addr_table come from hardware API. It is not intended to be manipulated in upper layers of the driver. In add, current code for hif_set_arp_ipv4_filter() is too dumb. It should pack data using the hardware representation instead of leaving all work to the caller. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-9-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx_mib.h | 16 +++++++++++++--- drivers/staging/wfx/sta.c | 25 +++++++------------------ 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index a8082508fbfd..a325c870b4ea 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -260,12 +260,22 @@ static inline int hif_keep_alive_period(struct wfx_vif *wvif, int period) &arg, sizeof(arg)); }; -static inline int hif_set_arp_ipv4_filter(struct wfx_vif *wvif, - struct hif_mib_arp_ip_addr_table *fp) +static inline int hif_set_arp_ipv4_filter(struct wfx_vif *wvif, int idx, + __be32 *addr) { + struct hif_mib_arp_ip_addr_table arg = { + .condition_idx = idx, + .arp_enable = HIF_ARP_NS_FILTERING_DISABLE, + }; + + if (addr) { + // Caution: type of addr is __be32 + memcpy(arg.ipv4_address, addr, sizeof(arg.ipv4_address)); + arg.arp_enable = HIF_ARP_NS_FILTERING_ENABLE; + } return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_ARP_IP_ADDRESSES_TABLE, - fp, sizeof(*fp)); + &arg, sizeof(arg)); } static inline int hif_use_multi_tx_conf(struct wfx_dev *wdev, diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 339acbce96fb..8c55089b1ea4 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -915,30 +915,19 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; bool do_join = false; int i; - int nb_arp_addr; mutex_lock(&wdev->conf_mutex); /* TODO: BSS_CHANGED_QOS */ if (changed & BSS_CHANGED_ARP_FILTER) { - struct hif_mib_arp_ip_addr_table filter = { }; - - nb_arp_addr = info->arp_addr_cnt; - if (nb_arp_addr <= 0 || nb_arp_addr > HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES) - nb_arp_addr = 0; - for (i = 0; i < HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES; i++) { - filter.condition_idx = i; - if (i < nb_arp_addr) { - // Caution: type of arp_addr_list[i] is __be32 - memcpy(filter.ipv4_address, - &info->arp_addr_list[i], - sizeof(filter.ipv4_address)); - filter.arp_enable = HIF_ARP_NS_FILTERING_ENABLE; - } else { - filter.arp_enable = HIF_ARP_NS_FILTERING_DISABLE; - } - hif_set_arp_ipv4_filter(wvif, &filter); + __be32 *arp_addr = &info->arp_addr_list[i]; + + if (info->arp_addr_cnt > HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES) + arp_addr = NULL; + if (i >= info->arp_addr_cnt) + arp_addr = NULL; + hif_set_arp_ipv4_filter(wvif, i, arp_addr); } } From 09779276f1baea08985e08587319c8fed806b020 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:14 +0000 Subject: [PATCH 252/353] staging: wfx: simplify hif_start() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structure hif_req_start come from hardware API. It is not intended to be manipulated in upper layers of the driver. In add, current code for hif_start() is too dumb. It should pack data with hardware representation instead of leaving all work to the caller. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-10-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx.c | 17 ++++++++++----- drivers/staging/wfx/hif_tx.h | 5 ++++- drivers/staging/wfx/sta.c | 40 ++++++++++++------------------------ 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index d8e159670eae..be3138590a4f 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -409,16 +409,23 @@ int hif_set_pm(struct wfx_vif *wvif, bool ps, int dynamic_ps_timeout) return ret; } -int hif_start(struct wfx_vif *wvif, const struct hif_req_start *arg) +int hif_start(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, + const struct ieee80211_channel *channel) { int ret; struct hif_msg *hif; struct hif_req_start *body = wfx_alloc_hif(sizeof(*body), &hif); - memcpy(body, arg, sizeof(*body)); - cpu_to_le16s(&body->channel_number); - cpu_to_le32s(&body->beacon_interval); - cpu_to_le32s(&body->basic_rate_set); + body->dtim_period = conf->dtim_period, + body->short_preamble = conf->use_short_preamble, + body->channel_number = cpu_to_le16(channel->hw_value), + body->beacon_interval = cpu_to_le32(conf->beacon_int); + body->basic_rate_set = + cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, conf->basic_rates)); + if (!conf->hidden_ssid) { + body->ssid_length = conf->ssid_len; + memcpy(body->ssid, conf->ssid, conf->ssid_len); + } wfx_fill_header(hif, wvif->id, HIF_REQ_ID_START, sizeof(*body)); ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); kfree(hif); diff --git a/drivers/staging/wfx/hif_tx.h b/drivers/staging/wfx/hif_tx.h index e8855ead3a18..fbaed991b112 100644 --- a/drivers/staging/wfx/hif_tx.h +++ b/drivers/staging/wfx/hif_tx.h @@ -12,6 +12,8 @@ #include "hif_api_cmd.h" +struct ieee80211_channel; +struct ieee80211_bss_conf; struct ieee80211_tx_queue_params; struct cfg80211_scan_request; struct wfx_dev; @@ -51,7 +53,8 @@ int hif_add_key(struct wfx_dev *wdev, const struct hif_req_add_key *arg); int hif_remove_key(struct wfx_dev *wdev, int idx); int hif_set_edca_queue_params(struct wfx_vif *wvif, u16 queue, const struct ieee80211_tx_queue_params *arg); -int hif_start(struct wfx_vif *wvif, const struct hif_req_start *arg); +int hif_start(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, + const struct ieee80211_channel *channel); int hif_beacon_transmit(struct wfx_vif *wvif, bool enable); int hif_map_link(struct wfx_vif *wvif, u8 *mac_addr, int flags, int sta_id); int hif_update_ie(struct wfx_vif *wvif, const struct hif_ie_flags *target_frame, diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 8c55089b1ea4..660a75024f4b 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -740,38 +740,24 @@ static void wfx_set_cts_work(struct work_struct *work) static int wfx_start_ap(struct wfx_vif *wvif) { int ret; - struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf; - struct hif_req_start start = { - .channel_number = wvif->channel->hw_value, - .beacon_interval = conf->beacon_int, - .dtim_period = conf->dtim_period, - .short_preamble = conf->use_short_preamble, - .basic_rate_set = wfx_rate_mask_to_hw(wvif->wdev, - conf->basic_rates), - }; - memset(start.ssid, 0, sizeof(start.ssid)); - if (!conf->hidden_ssid) { - start.ssid_length = conf->ssid_len; - memcpy(start.ssid, conf->ssid, start.ssid_length); - } - - wvif->beacon_int = conf->beacon_int; - wvif->dtim_period = conf->dtim_period; + wvif->beacon_int = wvif->vif->bss_conf.beacon_int; + wvif->dtim_period = wvif->vif->bss_conf.dtim_period; memset(&wvif->link_id_db, 0, sizeof(wvif->link_id_db)); wvif->wdev->tx_burst_idx = -1; - ret = hif_start(wvif, &start); - if (!ret) - ret = wfx_upload_keys(wvif); - if (!ret) { - if (wvif_count(wvif->wdev) <= 1) - hif_set_block_ack_policy(wvif, 0xFF, 0xFF); - wvif->state = WFX_STATE_AP; - wfx_update_filtering(wvif); - } - return ret; + ret = hif_start(wvif, &wvif->vif->bss_conf, wvif->channel); + if (ret) + return ret; + ret = wfx_upload_keys(wvif); + if (ret) + return ret; + if (wvif_count(wvif->wdev) <= 1) + hif_set_block_ack_policy(wvif, 0xFF, 0xFF); + wvif->state = WFX_STATE_AP; + wfx_update_filtering(wvif); + return 0; } static int wfx_update_beaconing(struct wfx_vif *wvif) From dfa45cb4bda4af22a25f7a58063d16997730a3b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:16 +0000 Subject: [PATCH 253/353] staging: wfx: use specialized structs for HIF arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of the commands that are sent to device should take struct in argument. In the current code, when this struct is binary compatible with a __le32, the driver use a __le32. This behavior is error prone. This patch fixes that and uses the specialized structs instead. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-11-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx.c | 4 ++-- drivers/staging/wfx/hif_tx_mib.h | 27 ++++++++++++++++++--------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index be3138590a4f..2d541601e224 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -432,14 +432,14 @@ int hif_start(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, return ret; } -int hif_beacon_transmit(struct wfx_vif *wvif, bool enable_beaconing) +int hif_beacon_transmit(struct wfx_vif *wvif, bool enable) { int ret; struct hif_msg *hif; struct hif_req_beacon_transmit *body = wfx_alloc_hif(sizeof(*body), &hif); - body->enable_beaconing = enable_beaconing ? 1 : 0; + body->enable_beaconing = enable ? 1 : 0; wfx_fill_header(hif, wvif->id, HIF_REQ_ID_BEACON_TRANSMIT, sizeof(*body)); ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index a325c870b4ea..5b39200bd697 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -278,10 +278,11 @@ static inline int hif_set_arp_ipv4_filter(struct wfx_vif *wvif, int idx, &arg, sizeof(arg)); } -static inline int hif_use_multi_tx_conf(struct wfx_dev *wdev, - bool enabled) +static inline int hif_use_multi_tx_conf(struct wfx_dev *wdev, bool enable) { - __le32 arg = enabled ? cpu_to_le32(1) : 0; + struct hif_mib_gl_set_multi_msg arg = { + .enable_multi_tx_conf = enable, + }; return hif_write_mib(wdev, -1, HIF_MIB_ID_GL_SET_MULTI_MSG, &arg, sizeof(arg)); @@ -306,7 +307,9 @@ static inline int hif_set_uapsd_info(struct wfx_vif *wvif, unsigned long val) static inline int hif_erp_use_protection(struct wfx_vif *wvif, bool enable) { - __le32 arg = enable ? cpu_to_le32(1) : 0; + struct hif_mib_non_erp_protection arg = { + .use_cts_to_self = enable, + }; return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_NON_ERP_PROTECTION, &arg, sizeof(arg)); @@ -314,16 +317,18 @@ static inline int hif_erp_use_protection(struct wfx_vif *wvif, bool enable) static inline int hif_slot_time(struct wfx_vif *wvif, int val) { - __le32 arg = cpu_to_le32(val); + struct hif_mib_slot_time arg = { + .slot_time = cpu_to_le32(val), + }; return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_SLOT_TIME, &arg, sizeof(arg)); } -static inline int hif_dual_cts_protection(struct wfx_vif *wvif, bool val) +static inline int hif_dual_cts_protection(struct wfx_vif *wvif, bool enable) { struct hif_mib_set_ht_protection arg = { - .dual_cts_prot = val, + .dual_cts_prot = enable, }; return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_SET_HT_PROTECTION, @@ -332,7 +337,9 @@ static inline int hif_dual_cts_protection(struct wfx_vif *wvif, bool val) static inline int hif_wep_default_key_id(struct wfx_vif *wvif, int val) { - __le32 arg = cpu_to_le32(val); + struct hif_mib_wep_default_key_id arg = { + .wep_default_key_id = val, + }; return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID, @@ -341,7 +348,9 @@ static inline int hif_wep_default_key_id(struct wfx_vif *wvif, int val) static inline int hif_rts_threshold(struct wfx_vif *wvif, int val) { - __le32 arg = cpu_to_le32(val > 0 ? val : 0xFFFF); + struct hif_mib_dot11_rts_threshold arg = { + .threshold = cpu_to_le32(val > 0 ? val : 0xFFFF), + }; return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_DOT11_RTS_THRESHOLD, &arg, sizeof(arg)); From c08ffbf7c02bddedda9e2945a9934e2651436706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:17 +0000 Subject: [PATCH 254/353] staging: wfx: retrieve ampdu_density from sta->ht_cap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wvif->ht_info.ht_cap is a useless copy of sta->ht_cap. It makes no sense to rely on it. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-12-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 660a75024f4b..f13a5b41735c 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -825,13 +825,6 @@ static int wfx_ht_greenfield(const struct wfx_ht_info *ht_info) IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); } -static int wfx_ht_ampdu_density(const struct wfx_ht_info *ht_info) -{ - if (!wfx_is_ht(ht_info)) - return 0; - return ht_info->ht_cap.ampdu_density; -} - static void wfx_join_finalize(struct wfx_vif *wvif, struct ieee80211_bss_conf *info) { @@ -870,7 +863,8 @@ static void wfx_join_finalize(struct wfx_vif *wvif, association_mode.short_preamble = info->use_short_preamble; association_mode.basic_rate_set = cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, info->basic_rates)); association_mode.greenfield = wfx_ht_greenfield(&wvif->ht_info); - association_mode.mpdu_start_spacing = wfx_ht_ampdu_density(&wvif->ht_info); + if (sta && sta->ht_cap.ht_supported) + association_mode.mpdu_start_spacing = sta->ht_cap.ampdu_density; wfx_cqm_bssloss_sm(wvif, 0, 0, 0); cancel_work_sync(&wvif->unjoin_work); From 08dced7f7fe921a3880fd799583a5a85c348b85d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:19 +0000 Subject: [PATCH 255/353] staging: wfx: retrieve greenfield mode from sta->ht_cap and bss_conf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wvif->ht_info contains useless copies of sta->ht_cap and bss_conf->ht_operation_mode. Prefer to retrieve information from the original structs instead of rely on wvif->ht_info. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-13-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index f13a5b41735c..fcd9fe66e417 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -817,14 +817,6 @@ static int wfx_is_ht(const struct wfx_ht_info *ht_info) return ht_info->channel_type != NL80211_CHAN_NO_HT; } -static int wfx_ht_greenfield(const struct wfx_ht_info *ht_info) -{ - return wfx_is_ht(ht_info) && - (ht_info->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && - !(ht_info->operation_mode & - IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); -} - static void wfx_join_finalize(struct wfx_vif *wvif, struct ieee80211_bss_conf *info) { @@ -849,9 +841,8 @@ static void wfx_join_finalize(struct wfx_vif *wvif, } rcu_read_unlock(); - /* Non Greenfield stations present */ - if (wvif->ht_info.operation_mode & - IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) + if (sta && + info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) hif_dual_cts_protection(wvif, true); else hif_dual_cts_protection(wvif, false); @@ -862,7 +853,10 @@ static void wfx_join_finalize(struct wfx_vif *wvif, association_mode.spacing = 1; association_mode.short_preamble = info->use_short_preamble; association_mode.basic_rate_set = cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, info->basic_rates)); - association_mode.greenfield = wfx_ht_greenfield(&wvif->ht_info); + if (sta && sta->ht_cap.ht_supported && + !(info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)) + association_mode.greenfield = + !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); if (sta && sta->ht_cap.ht_supported) association_mode.mpdu_start_spacing = sta->ht_cap.ampdu_density; From 811ed3e2aba3ca6d99b13704a406e518efa832d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:20 +0000 Subject: [PATCH 256/353] staging: wfx: drop struct wfx_ht_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This struct is no more used. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-14-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 18 +++--------------- drivers/staging/wfx/sta.h | 6 ------ drivers/staging/wfx/wfx.h | 1 - 3 files changed, 3 insertions(+), 22 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index fcd9fe66e417..dd2d0422c9ca 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -517,7 +517,6 @@ static void wfx_do_unjoin(struct wfx_vif *wvif) wfx_update_filtering(wvif); memset(&wvif->bss_params, 0, sizeof(wvif->bss_params)); wvif->setbssparams_done = false; - memset(&wvif->ht_info, 0, sizeof(wvif->ht_info)); done: mutex_unlock(&wvif->wdev->conf_mutex); @@ -812,11 +811,6 @@ static int wfx_upload_beacon(struct wfx_vif *wvif) return 0; } -static int wfx_is_ht(const struct wfx_ht_info *ht_info) -{ - return ht_info->channel_type != NL80211_CHAN_NO_HT; -} - static void wfx_join_finalize(struct wfx_vif *wvif, struct ieee80211_bss_conf *info) { @@ -830,17 +824,12 @@ static void wfx_join_finalize(struct wfx_vif *wvif, rcu_read_lock(); if (info->bssid && !info->ibss_joined) sta = ieee80211_find_sta(wvif->vif, info->bssid); - if (sta) { - wvif->ht_info.ht_cap = sta->ht_cap; + rcu_read_unlock(); + if (sta) wvif->bss_params.operational_rate_set = wfx_rate_mask_to_hw(wvif->wdev, sta->supp_rates[wvif->channel->band]); - wvif->ht_info.operation_mode = info->ht_operation_mode; - } else { - memset(&wvif->ht_info, 0, sizeof(wvif->ht_info)); + else wvif->bss_params.operational_rate_set = -1; - } - rcu_read_unlock(); - if (sta && info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) hif_dual_cts_protection(wvif, true); @@ -1224,7 +1213,6 @@ int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, WARN(wvif->channel, "channel overwrite"); wvif->channel = ch; - wvif->ht_info.channel_type = cfg80211_get_chandef_type(&conf->def); return 0; } diff --git a/drivers/staging/wfx/sta.h b/drivers/staging/wfx/sta.h index b5d8d6494157..e0b54332e98a 100644 --- a/drivers/staging/wfx/sta.h +++ b/drivers/staging/wfx/sta.h @@ -23,12 +23,6 @@ enum wfx_state { WFX_STATE_AP, }; -struct wfx_ht_info { - struct ieee80211_sta_ht_cap ht_cap; - enum nl80211_channel_type channel_type; - u16 operation_mode; -}; - struct wfx_hif_event { struct list_head link; struct hif_ind_event evt; diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 0a3df382af03..ba6e0e923f4b 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -113,7 +113,6 @@ struct wfx_vif { u32 erp_info; int cqm_rssi_thold; bool setbssparams_done; - struct wfx_ht_info ht_info; unsigned long uapsd_mask; struct ieee80211_tx_queue_params edca_params[IEEE80211_NUM_ACS]; struct hif_req_set_bss_params bss_params; From f050f3dac6686903f001862cc7b67bd2dcaeaea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:21 +0000 Subject: [PATCH 257/353] staging: wfx: drop wdev->output_power MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mac80211 and the device are both able to control tx power per vif. But, the current code retrieve tx power from wfx_config(). So, it does not allow to setup the tx power independently for each vif. Driver just has to rely on bss_conf->txpower to get the correct information. In add, it is no more necessary to protect access to wdev->output_power with scan_lock. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-15-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/scan.c | 4 ++-- drivers/staging/wfx/sta.c | 16 ++-------------- drivers/staging/wfx/wfx.h | 2 -- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index 8e0ac89fd28f..5cc9df5eb6a1 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -60,8 +60,8 @@ static int send_scan_req(struct wfx_vif *wvif, if (timeout < 0) return timeout; ret = wait_for_completion_timeout(&wvif->scan_complete, timeout); - if (req->channels[start_idx]->max_power != wvif->wdev->output_power) - hif_set_output_power(wvif, wvif->wdev->output_power); + if (req->channels[start_idx]->max_power != wvif->vif->bss_conf.txpower) + hif_set_output_power(wvif, wvif->vif->bss_conf.txpower); wfx_tx_unlock(wvif->wdev); if (!ret) { dev_notice(wvif->wdev->dev, "scan timeout\n"); diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index dd2d0422c9ca..a0f19d33e972 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -503,7 +503,6 @@ static void wfx_do_unjoin(struct wfx_vif *wvif) hif_keep_alive_period(wvif, 0); hif_reset(wvif, false); wfx_tx_policy_init(wvif); - hif_set_output_power(wvif, wvif->wdev->output_power); wvif->dtim_period = 0; hif_set_macaddr(wvif, wvif->vif->addr); wfx_free_event_queue(wvif); @@ -990,11 +989,8 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, info->cqm_rssi_hyst); } - if (changed & BSS_CHANGED_TXPOWER && - info->txpower != wdev->output_power) { - wdev->output_power = info->txpower; - hif_set_output_power(wvif, wdev->output_power); - } + if (changed & BSS_CHANGED_TXPOWER) + hif_set_output_power(wvif, info->txpower); mutex_unlock(&wdev->conf_mutex); if (do_join) @@ -1232,7 +1228,6 @@ int wfx_config(struct ieee80211_hw *hw, u32 changed) { int ret = 0; struct wfx_dev *wdev = hw->priv; - struct ieee80211_conf *conf = &hw->conf; struct wfx_vif *wvif; // FIXME: Interface id should not been hardcoded @@ -1242,13 +1237,7 @@ int wfx_config(struct ieee80211_hw *hw, u32 changed) return 0; } - mutex_lock(&wvif->scan_lock); mutex_lock(&wdev->conf_mutex); - if (changed & IEEE80211_CONF_CHANGE_POWER) { - wdev->output_power = conf->power_level; - hif_set_output_power(wvif, wdev->output_power); - } - if (changed & IEEE80211_CONF_CHANGE_PS) { wvif = NULL; while ((wvif = wvif_iterate(wdev, wvif)) != NULL) @@ -1257,7 +1246,6 @@ int wfx_config(struct ieee80211_hw *hw, u32 changed) } mutex_unlock(&wdev->conf_mutex); - mutex_unlock(&wvif->scan_lock); return ret; } diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index ba6e0e923f4b..155dbe5704c9 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -59,8 +59,6 @@ struct wfx_dev { struct hif_rx_stats rx_stats; struct mutex rx_stats_lock; - - int output_power; }; struct wfx_vif { From 9bf7ad8c93cede3f58d0bfd4b869790401ca6d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:23 +0000 Subject: [PATCH 258/353] staging: wfx: simplify wfx_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that wfx_config() only handles IEEE80211_CONF_CHANGE_PS, it can be simplified. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-16-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index a0f19d33e972..451d0108a1b0 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -1230,22 +1230,13 @@ int wfx_config(struct ieee80211_hw *hw, u32 changed) struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif; - // FIXME: Interface id should not been hardcoded - wvif = wdev_to_wvif(wdev, 0); - if (!wvif) { - WARN(1, "interface 0 does not exist anymore"); - return 0; - } - - mutex_lock(&wdev->conf_mutex); if (changed & IEEE80211_CONF_CHANGE_PS) { + mutex_lock(&wdev->conf_mutex); wvif = NULL; while ((wvif = wvif_iterate(wdev, wvif)) != NULL) ret = wfx_update_pm(wvif); - wvif = wdev_to_wvif(wdev, 0); + mutex_unlock(&wdev->conf_mutex); } - - mutex_unlock(&wdev->conf_mutex); return ret; } From d8a92d918612fca365d5b3ed75fc9e41090366ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:24 +0000 Subject: [PATCH 259/353] staging: wfx: rename wfx_upload_beacon() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In fact, wfx_upload_beacon() uploads beacon and probe response. So, rename it in wfx_upload_ap_templates(). The call to wfx_fwd_probe_req() has nothing to do with template uploading, so relocate it. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-17-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 451d0108a1b0..fdde7ab92302 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -780,7 +780,7 @@ static int wfx_update_beaconing(struct wfx_vif *wvif) return 0; } -static int wfx_upload_beacon(struct wfx_vif *wvif) +static int wfx_upload_ap_templates(struct wfx_vif *wvif) { struct sk_buff *skb; struct ieee80211_mgmt *mgmt; @@ -805,7 +805,6 @@ static int wfx_upload_beacon(struct wfx_vif *wvif) hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES, API_RATE_INDEX_B_1MBPS); - wfx_fwd_probe_req(wvif, false); dev_kfree_skb(skb); return 0; } @@ -900,7 +899,8 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, changed & BSS_CHANGED_IBSS) { wvif->beacon_int = info->beacon_int; wfx_update_beaconing(wvif); - wfx_upload_beacon(wvif); + wfx_upload_ap_templates(wvif); + wfx_fwd_probe_req(wvif, false); } if (changed & BSS_CHANGED_BEACON_ENABLED && From 305f710995f72a752154c22cf1f5814e661be376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:26 +0000 Subject: [PATCH 260/353] staging: wfx: simplify wfx_upload_ap_templates() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function built probe response from data retrieved in beacon. Yet, this job can be done with ieee80211_proberesp_get(). So, we can simplify that code (and fix bugs like inclusion of TIM in probe responses). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-18-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index fdde7ab92302..1181203489f0 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -783,7 +783,6 @@ static int wfx_update_beaconing(struct wfx_vif *wvif) static int wfx_upload_ap_templates(struct wfx_vif *wvif) { struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; if (wvif->vif->type == NL80211_IFTYPE_STATION || wvif->vif->type == NL80211_IFTYPE_MONITOR || @@ -795,14 +794,11 @@ static int wfx_upload_ap_templates(struct wfx_vif *wvif) return -ENOMEM; hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN, API_RATE_INDEX_B_1MBPS); + dev_kfree_skb(skb); - /* TODO: Distill probe resp; remove TIM and any other beacon-specific - * IEs - */ - mgmt = (void *)skb->data; - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); - + skb = ieee80211_proberesp_get(wvif->wdev->hw, wvif->vif); + if (!skb) + return -ENOMEM; hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES, API_RATE_INDEX_B_1MBPS); dev_kfree_skb(skb); From 0b2b0595cec64f89814cd1e5fbcbc36e7540443d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:27 +0000 Subject: [PATCH 261/353] staging: wfx: simplify wfx_update_beaconing() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove most of indentation of wfx_update_beaconing() by reworking the error handling. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-19-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 1181203489f0..0c73691ab736 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -760,23 +760,17 @@ static int wfx_start_ap(struct wfx_vif *wvif) static int wfx_update_beaconing(struct wfx_vif *wvif) { - struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf; - - if (wvif->vif->type == NL80211_IFTYPE_AP) { - /* TODO: check if changed channel, band */ - if (wvif->state != WFX_STATE_AP || - wvif->beacon_int != conf->beacon_int) { - wfx_tx_lock_flush(wvif->wdev); - if (wvif->state != WFX_STATE_PASSIVE) { - hif_reset(wvif, false); - wfx_tx_policy_init(wvif); - } - wvif->state = WFX_STATE_PASSIVE; - wfx_start_ap(wvif); - wfx_tx_unlock(wvif->wdev); - } else { - } - } + if (wvif->vif->type != NL80211_IFTYPE_AP) + return 0; + if (wvif->state == WFX_STATE_AP && + wvif->beacon_int == wvif->vif->bss_conf.beacon_int) + return 0; + wfx_tx_lock_flush(wvif->wdev); + hif_reset(wvif, false); + wfx_tx_policy_init(wvif); + wvif->state = WFX_STATE_PASSIVE; + wfx_start_ap(wvif); + wfx_tx_unlock(wvif->wdev); return 0; } From 044df863c98d4d4be6306f3251a9397f22418946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:29 +0000 Subject: [PATCH 262/353] staging: wfx: fix __wfx_flush() when drop == false MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wfx_tx_queues_clear() only clear not yet sent requests. So, it always necessary to wait for tx_queue_stats.wait_link_id_empty whatever the value of "drop" argument. In add, it is not necessary to return with tx queue locked since all calls to __wfx_flush() unlock the tx queue just after the call to __wfx_tx_flush(). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-20-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/queue.c | 2 -- drivers/staging/wfx/sta.c | 42 ++++++++++--------------------------- 2 files changed, 11 insertions(+), 33 deletions(-) diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index abfbad7c9f75..92bb9a794f30 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -31,8 +31,6 @@ void wfx_tx_flush(struct wfx_dev *wdev) { int ret; - WARN(!atomic_read(&wdev->tx_lock), "tx_lock is not locked"); - // Do not wait for any reply if chip is frozen if (wdev->chip_frozen) return; diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 0c73691ab736..3d665eef8ba7 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -343,42 +343,25 @@ int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value) return 0; } -/* If successful, LOCKS the TX queue! */ static int __wfx_flush(struct wfx_dev *wdev, bool drop) { - int ret; - for (;;) { - if (drop) { + if (drop) wfx_tx_queues_clear(wdev); - } else { - ret = wait_event_timeout( - wdev->tx_queue_stats.wait_link_id_empty, - wfx_tx_queues_is_empty(wdev), - 2 * HZ); - } - - if (!drop && ret <= 0) { - ret = -ETIMEDOUT; - break; - } - ret = 0; - - wfx_tx_lock_flush(wdev); - if (!wfx_tx_queues_is_empty(wdev)) { - /* Highly unlikely: WSM requeued frames. */ - wfx_tx_unlock(wdev); - continue; - } - break; + if (wait_event_timeout(wdev->tx_queue_stats.wait_link_id_empty, + wfx_tx_queues_is_empty(wdev), + 2 * HZ) <= 0) + return -ETIMEDOUT; + wfx_tx_flush(wdev); + if (wfx_tx_queues_is_empty(wdev)) + return 0; + dev_warn(wdev->dev, "frames queued while flushing tx queues"); } - return ret; } void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop) { - struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif; if (vif) { @@ -389,10 +372,8 @@ void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, !wvif->enable_beacon) drop = true; } - // FIXME: only flush requested vif - if (!__wfx_flush(wdev, drop)) - wfx_tx_unlock(wdev); + __wfx_flush(hw->priv, drop); } /* WSM callbacks */ @@ -1046,8 +1027,7 @@ static int wfx_set_tim_impl(struct wfx_vif *wvif, bool aid0_bit_set) skb = ieee80211_beacon_get_tim(wvif->wdev->hw, wvif->vif, &tim_offset, &tim_length); if (!skb) { - if (!__wfx_flush(wvif->wdev, true)) - wfx_tx_unlock(wvif->wdev); + __wfx_flush(wvif->wdev, true); return -ENOENT; } tim_ptr = skb->data + tim_offset; From 50a4fb47e9ac5853e7143367b2877e348ca86ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:30 +0000 Subject: [PATCH 263/353] staging: wfx: simplify wfx_flush() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current code of wfx_flush() force to drop packets in some contexts. However, there is no obvious reasons to do that. It looks like a workaround for a bug with the old implementation of __wfx_flush(). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-21-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 3d665eef8ba7..ae01f7be0ddb 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -362,17 +362,7 @@ static int __wfx_flush(struct wfx_dev *wdev, bool drop) void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop) { - struct wfx_vif *wvif; - - if (vif) { - wvif = (struct wfx_vif *) vif->drv_priv; - if (wvif->vif->type == NL80211_IFTYPE_MONITOR) - drop = true; - if (wvif->vif->type == NL80211_IFTYPE_AP && - !wvif->enable_beacon) - drop = true; - } - // FIXME: only flush requested vif + // FIXME: only flush requested vif and queues __wfx_flush(hw->priv, drop); } From b0674e0675520beeca7a52ae7e610d751996e8ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:32 +0000 Subject: [PATCH 264/353] staging: wfx: simplify update of DTIM period MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current code parse the TIM and retrieve the DTIM period. It is far easier to rely on bss_info_changed() for this job. It is no more necessary to run task asynchronously. So set_beacon_wakeup_period_work is now useless. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-22-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_rx.c | 14 -------------- drivers/staging/wfx/sta.c | 19 ++++++------------- drivers/staging/wfx/wfx.h | 2 -- 3 files changed, 6 insertions(+), 29 deletions(-) diff --git a/drivers/staging/wfx/data_rx.c b/drivers/staging/wfx/data_rx.c index d460c0ffca1f..0ab71c911f84 100644 --- a/drivers/staging/wfx/data_rx.c +++ b/drivers/staging/wfx/data_rx.c @@ -173,20 +173,6 @@ void wfx_rx_cb(struct wfx_vif *wvif, !arg->status && wvif->vif && ether_addr_equal(ieee80211_get_SA(frame), wvif->vif->bss_conf.bssid)) { - const u8 *tim_ie; - u8 *ies = mgmt->u.beacon.variable; - size_t ies_len = skb->len - (ies - skb->data); - - tim_ie = cfg80211_find_ie(WLAN_EID_TIM, ies, ies_len); - if (tim_ie) { - struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *)&tim_ie[2]; - - if (wvif->dtim_period != tim->dtim_period) { - wvif->dtim_period = tim->dtim_period; - schedule_work(&wvif->set_beacon_wakeup_period_work); - } - } - /* Disable beacon filter once we're associated... */ if (wvif->disable_beacon_filter && (wvif->vif->bss_conf.assoc || diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index ae01f7be0ddb..1af99b7930f4 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -446,15 +446,6 @@ static void wfx_bss_params_work(struct work_struct *work) mutex_unlock(&wvif->wdev->conf_mutex); } -static void wfx_set_beacon_wakeup_period_work(struct work_struct *work) -{ - struct wfx_vif *wvif = container_of(work, struct wfx_vif, - set_beacon_wakeup_period_work); - - hif_set_beacon_wakeup_period(wvif, wvif->dtim_period, - wvif->dtim_period); -} - static void wfx_do_unjoin(struct wfx_vif *wvif) { mutex_lock(&wvif->wdev->conf_mutex); @@ -466,7 +457,6 @@ static void wfx_do_unjoin(struct wfx_vif *wvif) goto done; cancel_work_sync(&wvif->update_filtering_work); - cancel_work_sync(&wvif->set_beacon_wakeup_period_work); wvif->state = WFX_STATE_PASSIVE; /* Unjoin is a reset. */ @@ -823,7 +813,8 @@ static void wfx_join_finalize(struct wfx_vif *wvif, hif_keep_alive_period(wvif, 30 /* sec */); hif_set_bss_params(wvif, &wvif->bss_params); wvif->setbssparams_done = true; - wfx_set_beacon_wakeup_period_work(&wvif->set_beacon_wakeup_period_work); + hif_set_beacon_wakeup_period(wvif, info->dtim_period, + info->dtim_period); wfx_update_pm(wvif); } } @@ -872,6 +863,10 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, } } + if (changed & BSS_CHANGED_BEACON_INFO) + hif_set_beacon_wakeup_period(wvif, info->dtim_period, + info->dtim_period); + /* assoc/disassoc, or maybe AID changed */ if (changed & BSS_CHANGED_ASSOC) { wfx_tx_lock_flush(wdev); @@ -1260,8 +1255,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) init_completion(&wvif->set_pm_mode_complete); complete(&wvif->set_pm_mode_complete); - INIT_WORK(&wvif->set_beacon_wakeup_period_work, - wfx_set_beacon_wakeup_period_work); INIT_WORK(&wvif->update_filtering_work, wfx_update_filtering_work); INIT_WORK(&wvif->bss_params_work, wfx_bss_params_work); INIT_WORK(&wvif->set_cts_work, wfx_set_cts_work); diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 155dbe5704c9..d201cceec1ab 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -101,8 +101,6 @@ struct wfx_vif { int dtim_period; int beacon_int; bool enable_beacon; - struct work_struct set_beacon_wakeup_period_work; - bool filter_bssid; bool fwd_probe_req; bool disable_beacon_filter; From 249802e8e226b869ad065bc56811410f83cbfcd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:34 +0000 Subject: [PATCH 265/353] staging: wfx: drop wvif->dtim_period MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is not necessary to keep a copy of dtim_period in wfx_vif. Prefer to just rely on bss_conf->dtim_period. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-23-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 20 ++++---------------- drivers/staging/wfx/wfx.h | 1 - 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 1af99b7930f4..376451433e9e 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -464,7 +464,6 @@ static void wfx_do_unjoin(struct wfx_vif *wvif) hif_keep_alive_period(wvif, 0); hif_reset(wvif, false); wfx_tx_policy_init(wvif); - wvif->dtim_period = 0; hif_set_macaddr(wvif, wvif->vif->addr); wfx_free_event_queue(wvif); cancel_work_sync(&wvif->event_handler_work); @@ -557,10 +556,6 @@ static void wfx_do_join(struct wfx_vif *wvif) wvif->beacon_int = 1; join.beacon_interval = wvif->beacon_int; - - // DTIM period will be set on first Beacon - wvif->dtim_period = 0; - join.channel_number = wvif->channel->hw_value; memcpy(join.bssid, bssid, sizeof(join.bssid)); @@ -701,8 +696,6 @@ static int wfx_start_ap(struct wfx_vif *wvif) int ret; wvif->beacon_int = wvif->vif->bss_conf.beacon_int; - wvif->dtim_period = wvif->vif->bss_conf.dtim_period; - memset(&wvif->link_id_db, 0, sizeof(wvif->link_id_db)); wvif->wdev->tx_burst_idx = -1; @@ -766,10 +759,7 @@ static void wfx_join_finalize(struct wfx_vif *wvif, struct ieee80211_sta *sta = NULL; struct hif_mib_set_association_mode association_mode = { }; - if (info->dtim_period) - wvif->dtim_period = info->dtim_period; wvif->beacon_int = info->beacon_int; - rcu_read_lock(); if (info->bssid && !info->ibss_joined) sta = ieee80211_find_sta(wvif->vif, info->bssid); @@ -804,9 +794,6 @@ static void wfx_join_finalize(struct wfx_vif *wvif, wvif->bss_params.beacon_lost_count = 20; wvif->bss_params.aid = info->aid; - if (wvif->dtim_period < 1) - wvif->dtim_period = 1; - hif_set_association_mode(wvif, &association_mode); if (!info->ibss_joined) { @@ -1055,9 +1042,10 @@ int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) static void wfx_mcast_start_work(struct work_struct *work) { - struct wfx_vif *wvif = container_of(work, struct wfx_vif, - mcast_start_work); - long tmo = wvif->dtim_period * TU_TO_JIFFIES(wvif->beacon_int + 20); + struct wfx_vif *wvif = + container_of(work, struct wfx_vif, mcast_start_work); + struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf; + long tmo = conf->dtim_period * TU_TO_JIFFIES(wvif->beacon_int + 20); cancel_work_sync(&wvif->mcast_stop_work); if (!wvif->aid0_bit_set) { diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index d201cceec1ab..bd4b55e07c73 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -98,7 +98,6 @@ struct wfx_vif { spinlock_t ps_state_lock; struct work_struct set_tim_work; - int dtim_period; int beacon_int; bool enable_beacon; bool filter_bssid; From 9d443ffc588bbee103eddecd6b1994cf7d0b0ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:35 +0000 Subject: [PATCH 266/353] staging: wfx: drop wvif->enable_beacon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems that current code try to save calls to hif_beacon_transmit() by keeping a copy of the previous value of bss_conf->enable_beacon. However, hif_beacon_transmit() does not cost so much and mac80211 already take care to not send useless events. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-24-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 9 ++------- drivers/staging/wfx/wfx.h | 1 - 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 376451433e9e..dede6323bb17 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -843,12 +843,8 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_BEACON_ENABLED && - wvif->state != WFX_STATE_IBSS) { - if (wvif->enable_beacon != info->enable_beacon) { - hif_beacon_transmit(wvif, info->enable_beacon); - wvif->enable_beacon = info->enable_beacon; - } - } + wvif->state != WFX_STATE_IBSS) + hif_beacon_transmit(wvif, info->enable_beacon); if (changed & BSS_CHANGED_BEACON_INFO) hif_set_beacon_wakeup_period(wvif, info->dtim_period, @@ -1299,7 +1295,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw, } memset(wvif->link_id_db, 0, sizeof(wvif->link_id_db)); wvif->sta_asleep_mask = 0; - wvif->enable_beacon = false; wvif->mcast_tx = false; wvif->aid0_bit_set = false; wvif->mcast_buffered = false; diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index bd4b55e07c73..84cb3a83e5d9 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -99,7 +99,6 @@ struct wfx_vif { struct work_struct set_tim_work; int beacon_int; - bool enable_beacon; bool filter_bssid; bool fwd_probe_req; bool disable_beacon_filter; From ba366b9268263f7f86cf8e53e00bda84e238d29b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:37 +0000 Subject: [PATCH 267/353] staging: wfx: drop wvif->cqm_rssi_thold MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current code keeps a copy of bss_conf->cqm_rssi_thold in wfx_vif. There is no sane reason for that. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-25-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 6 ++---- drivers/staging/wfx/wfx.h | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index dede6323bb17..021daa9f7a33 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -377,7 +377,7 @@ static void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi) int cqm_evt; rcpi_rssi = raw_rcpi_rssi / 2 - 110; - if (rcpi_rssi <= wvif->cqm_rssi_thold) + if (rcpi_rssi <= wvif->vif->bss_conf.cqm_rssi_thold) cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; else cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; @@ -922,11 +922,9 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC || changed & BSS_CHANGED_ERP_SLOT) hif_slot_time(wvif, info->use_short_slot ? 9 : 20); - if (changed & BSS_CHANGED_ASSOC || changed & BSS_CHANGED_CQM) { - wvif->cqm_rssi_thold = info->cqm_rssi_thold; + if (changed & BSS_CHANGED_ASSOC || changed & BSS_CHANGED_CQM) hif_set_rcpi_rssi_threshold(wvif, info->cqm_rssi_thold, info->cqm_rssi_hyst); - } if (changed & BSS_CHANGED_TXPOWER) hif_set_output_power(wvif, info->txpower); diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 84cb3a83e5d9..1b487d96eca2 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -105,7 +105,6 @@ struct wfx_vif { struct work_struct update_filtering_work; u32 erp_info; - int cqm_rssi_thold; bool setbssparams_done; unsigned long uapsd_mask; struct ieee80211_tx_queue_params edca_params[IEEE80211_NUM_ACS]; From 963aff5728a0295fe90146289c2a9251024575a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:38 +0000 Subject: [PATCH 268/353] staging: wfx: drop wvif->setbssparams_done MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit setbssparams_done was here to ensure that the firmware does not enable powersave before to get the first beacon. However, mac80211 already ensures it gets a beacon before to associate to the BSS. And even, if it won't, the firmware wake up at least on every DTIM, which is sufficient to finalize the association. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-26-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 8 +++----- drivers/staging/wfx/wfx.h | 1 - 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 021daa9f7a33..7abe272ddc0d 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -326,8 +326,7 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, hif_set_edca_queue_params(wvif, queue, params); if (wvif->vif->type == NL80211_IFTYPE_STATION) { hif_set_uapsd_info(wvif, wvif->uapsd_mask); - if (wvif->setbssparams_done && wvif->state == WFX_STATE_STA) - ret = wfx_update_pm(wvif); + wfx_update_pm(wvif); } mutex_unlock(&wdev->conf_mutex); return ret; @@ -475,7 +474,6 @@ static void wfx_do_unjoin(struct wfx_vif *wvif) wvif->disable_beacon_filter = false; wfx_update_filtering(wvif); memset(&wvif->bss_params, 0, sizeof(wvif->bss_params)); - wvif->setbssparams_done = false; done: mutex_unlock(&wvif->wdev->conf_mutex); @@ -799,7 +797,6 @@ static void wfx_join_finalize(struct wfx_vif *wvif, if (!info->ibss_joined) { hif_keep_alive_period(wvif, 30 /* sec */); hif_set_bss_params(wvif, &wvif->bss_params); - wvif->setbssparams_done = true; hif_set_beacon_wakeup_period(wvif, info->dtim_period, info->dtim_period); wfx_update_pm(wvif); @@ -1224,7 +1221,8 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) INIT_WORK(&wvif->mcast_stop_work, wfx_mcast_stop_work); timer_setup(&wvif->mcast_timeout, wfx_mcast_timeout, 0); - wvif->setbssparams_done = false; + memset(&wvif->bss_params, 0, sizeof(wvif->bss_params)); + mutex_init(&wvif->bss_loss_lock); INIT_DELAYED_WORK(&wvif->bss_loss_work, wfx_bss_loss_work); diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 1b487d96eca2..5e1a763eb4b5 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -105,7 +105,6 @@ struct wfx_vif { struct work_struct update_filtering_work; u32 erp_info; - bool setbssparams_done; unsigned long uapsd_mask; struct ieee80211_tx_queue_params edca_params[IEEE80211_NUM_ACS]; struct hif_req_set_bss_params bss_params; From deb7734ea984ec6909f4dc86b4707f91301c9ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:40 +0000 Subject: [PATCH 269/353] staging: wfx: drop wfx_set_cts_work() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wfx_bss_info_changed() is not called from atomic contexts. So, it is not necessary to raise an asynchronous work to change ERP. Thus wfx_set_cts_work() become useless. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-27-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 40 +++++++++------------------------------ drivers/staging/wfx/wfx.h | 2 -- 2 files changed, 9 insertions(+), 33 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 7abe272ddc0d..e02ebc39ed41 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -671,24 +671,6 @@ int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return 0; } -static void wfx_set_cts_work(struct work_struct *work) -{ - struct wfx_vif *wvif = container_of(work, struct wfx_vif, set_cts_work); - u8 erp_ie[3] = { WLAN_EID_ERP_INFO, 1, 0 }; - struct hif_ie_flags target_frame = { - .beacon = 1, - }; - - mutex_lock(&wvif->wdev->conf_mutex); - erp_ie[2] = wvif->erp_info; - mutex_unlock(&wvif->wdev->conf_mutex); - - hif_erp_use_protection(wvif, erp_ie[2] & WLAN_ERP_USE_PROTECTION); - - if (wvif->vif->type != NL80211_IFTYPE_STATION) - hif_update_ie(wvif, &target_frame, erp_ie, sizeof(erp_ie)); -} - static int wfx_start_ap(struct wfx_vif *wvif) { int ret; @@ -896,24 +878,21 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, } } - /* ERP Protection */ if (changed & BSS_CHANGED_ASSOC || changed & BSS_CHANGED_ERP_CTS_PROT || changed & BSS_CHANGED_ERP_PREAMBLE) { - u32 prev_erp_info = wvif->erp_info; + struct hif_ie_flags target_frame = { + .beacon = 1, + }; + u8 erp_ie[3] = { WLAN_EID_ERP_INFO, 1, 0 }; + hif_erp_use_protection(wvif, info->use_cts_prot); if (info->use_cts_prot) - wvif->erp_info |= WLAN_ERP_USE_PROTECTION; - else if (!(prev_erp_info & WLAN_ERP_NON_ERP_PRESENT)) - wvif->erp_info &= ~WLAN_ERP_USE_PROTECTION; - + erp_ie[2] |= WLAN_ERP_USE_PROTECTION; if (info->use_short_preamble) - wvif->erp_info |= WLAN_ERP_BARKER_PREAMBLE; - else - wvif->erp_info &= ~WLAN_ERP_BARKER_PREAMBLE; - - if (prev_erp_info != wvif->erp_info) - schedule_work(&wvif->set_cts_work); + erp_ie[2] |= WLAN_ERP_BARKER_PREAMBLE; + if (wvif->vif->type != NL80211_IFTYPE_STATION) + hif_update_ie(wvif, &target_frame, erp_ie, sizeof(erp_ie)); } if (changed & BSS_CHANGED_ASSOC || changed & BSS_CHANGED_ERP_SLOT) @@ -1237,7 +1216,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) complete(&wvif->set_pm_mode_complete); INIT_WORK(&wvif->update_filtering_work, wfx_update_filtering_work); INIT_WORK(&wvif->bss_params_work, wfx_bss_params_work); - INIT_WORK(&wvif->set_cts_work, wfx_set_cts_work); INIT_WORK(&wvif->unjoin_work, wfx_unjoin_work); INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work); diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 5e1a763eb4b5..f56a91ea082d 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -104,12 +104,10 @@ struct wfx_vif { bool disable_beacon_filter; struct work_struct update_filtering_work; - u32 erp_info; unsigned long uapsd_mask; struct ieee80211_tx_queue_params edca_params[IEEE80211_NUM_ACS]; struct hif_req_set_bss_params bss_params; struct work_struct bss_params_work; - struct work_struct set_cts_work; int join_complete_status; struct work_struct unjoin_work; From d1072b04f57e0e3a8a6d164dd03b4cc42711ea05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:41 +0000 Subject: [PATCH 270/353] staging: wfx: SSID should be provided to hif_start() even if hidden MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SSID is hidden in beacon but firmware has to know to which probe requests it has to answer. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-28-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index 2d541601e224..8df6e43fe742 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -422,10 +422,8 @@ int hif_start(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, body->beacon_interval = cpu_to_le32(conf->beacon_int); body->basic_rate_set = cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, conf->basic_rates)); - if (!conf->hidden_ssid) { - body->ssid_length = conf->ssid_len; - memcpy(body->ssid, conf->ssid, conf->ssid_len); - } + body->ssid_length = conf->ssid_len; + memcpy(body->ssid, conf->ssid, conf->ssid_len); wfx_fill_header(hif, wvif->id, HIF_REQ_ID_START, sizeof(*body)); ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); kfree(hif); From a09343fc354d45973614e1120f15b5e03db8f972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:43 +0000 Subject: [PATCH 271/353] staging: wfx: simplify hif_update_ie() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hif_update_ie() is only called to change the beacon template. So, specialize this function and simplify the way to call it. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-29-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx.c | 5 ++--- drivers/staging/wfx/hif_tx.h | 3 +-- drivers/staging/wfx/sta.c | 10 ++-------- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index 8df6e43fe742..32eeba2fca47 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -461,15 +461,14 @@ int hif_map_link(struct wfx_vif *wvif, u8 *mac_addr, int flags, int sta_id) return ret; } -int hif_update_ie(struct wfx_vif *wvif, const struct hif_ie_flags *target_frame, - const u8 *ies, size_t ies_len) +int hif_update_ie_beacon(struct wfx_vif *wvif, const u8 *ies, size_t ies_len) { int ret; struct hif_msg *hif; int buf_len = sizeof(struct hif_req_update_ie) + ies_len; struct hif_req_update_ie *body = wfx_alloc_hif(buf_len, &hif); - memcpy(&body->ie_flags, target_frame, sizeof(struct hif_ie_flags)); + body->ie_flags.beacon = 1; body->num_ies = cpu_to_le16(1); memcpy(body->ie, ies, ies_len); wfx_fill_header(hif, wvif->id, HIF_REQ_ID_UPDATE_IE, buf_len); diff --git a/drivers/staging/wfx/hif_tx.h b/drivers/staging/wfx/hif_tx.h index fbaed991b112..924b889cad0a 100644 --- a/drivers/staging/wfx/hif_tx.h +++ b/drivers/staging/wfx/hif_tx.h @@ -57,8 +57,7 @@ int hif_start(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, const struct ieee80211_channel *channel); int hif_beacon_transmit(struct wfx_vif *wvif, bool enable); int hif_map_link(struct wfx_vif *wvif, u8 *mac_addr, int flags, int sta_id); -int hif_update_ie(struct wfx_vif *wvif, const struct hif_ie_flags *target_frame, - const u8 *ies, size_t ies_len); +int hif_update_ie_beacon(struct wfx_vif *wvif, const u8 *ies, size_t ies_len); int hif_sl_set_mac_key(struct wfx_dev *wdev, const u8 *slk_key, int destination); int hif_sl_config(struct wfx_dev *wdev, const unsigned long *bitmap); diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index e02ebc39ed41..395a282346b1 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -881,9 +881,6 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC || changed & BSS_CHANGED_ERP_CTS_PROT || changed & BSS_CHANGED_ERP_PREAMBLE) { - struct hif_ie_flags target_frame = { - .beacon = 1, - }; u8 erp_ie[3] = { WLAN_EID_ERP_INFO, 1, 0 }; hif_erp_use_protection(wvif, info->use_cts_prot); @@ -892,7 +889,7 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, if (info->use_short_preamble) erp_ie[2] |= WLAN_ERP_BARKER_PREAMBLE; if (wvif->vif->type != NL80211_IFTYPE_STATION) - hif_update_ie(wvif, &target_frame, erp_ie, sizeof(erp_ie)); + hif_update_ie_beacon(wvif, erp_ie, sizeof(erp_ie)); } if (changed & BSS_CHANGED_ASSOC || changed & BSS_CHANGED_ERP_SLOT) @@ -960,9 +957,6 @@ void wfx_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static int wfx_set_tim_impl(struct wfx_vif *wvif, bool aid0_bit_set) { struct sk_buff *skb; - struct hif_ie_flags target_frame = { - .beacon = 1, - }; u16 tim_offset, tim_length; u8 *tim_ptr; @@ -987,7 +981,7 @@ static int wfx_set_tim_impl(struct wfx_vif *wvif, bool aid0_bit_set) tim_ptr[4] &= ~1; } - hif_update_ie(wvif, &target_frame, tim_ptr, tim_length); + hif_update_ie_beacon(wvif, tim_ptr, tim_length); dev_kfree_skb(skb); return 0; From 9ced9b593741d0472dd1168ca87ca7186e3257f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:44 +0000 Subject: [PATCH 272/353] staging: wfx: simplify hif_join() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structure hif_req_join come from hardware API. It is not intended to be manipulated in upper layers of the driver. In add, current code for hif_join() is too dumb. It should pack data with hardware representation instead of leaving all work to the caller. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-30-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx.c | 25 ++++++++++++++------ drivers/staging/wfx/hif_tx.h | 3 ++- drivers/staging/wfx/sta.c | 45 ++++++++---------------------------- 3 files changed, 30 insertions(+), 43 deletions(-) diff --git a/drivers/staging/wfx/hif_tx.c b/drivers/staging/wfx/hif_tx.c index 32eeba2fca47..2428363371fa 100644 --- a/drivers/staging/wfx/hif_tx.c +++ b/drivers/staging/wfx/hif_tx.c @@ -288,18 +288,29 @@ int hif_stop_scan(struct wfx_vif *wvif) return ret; } -int hif_join(struct wfx_vif *wvif, const struct hif_req_join *arg) +int hif_join(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, + const struct ieee80211_channel *channel, const u8 *ssidie) { int ret; struct hif_msg *hif; struct hif_req_join *body = wfx_alloc_hif(sizeof(*body), &hif); - memcpy(body, arg, sizeof(struct hif_req_join)); - cpu_to_le16s(&body->channel_number); - cpu_to_le16s(&body->atim_window); - cpu_to_le32s(&body->ssid_length); - cpu_to_le32s(&body->beacon_interval); - cpu_to_le32s(&body->basic_rate_set); + WARN_ON(!conf->basic_rates); + body->infrastructure_bss_mode = !conf->ibss_joined; + body->short_preamble = conf->use_short_preamble; + if (channel && channel->flags & IEEE80211_CHAN_NO_IR) + body->probe_for_join = 0; + else + body->probe_for_join = 1; + body->channel_number = cpu_to_le16(channel->hw_value); + body->beacon_interval = cpu_to_le32(conf->beacon_int); + body->basic_rate_set = + cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, conf->basic_rates)); + memcpy(body->bssid, conf->bssid, sizeof(body->bssid)); + if (!conf->ibss_joined && ssidie) { + body->ssid_length = cpu_to_le32(ssidie[1]); + memcpy(body->ssid, &ssidie[2], ssidie[1]); + } wfx_fill_header(hif, wvif->id, HIF_REQ_ID_JOIN, sizeof(*body)); ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false); kfree(hif); diff --git a/drivers/staging/wfx/hif_tx.h b/drivers/staging/wfx/hif_tx.h index 924b889cad0a..20977e461718 100644 --- a/drivers/staging/wfx/hif_tx.h +++ b/drivers/staging/wfx/hif_tx.h @@ -45,7 +45,8 @@ int hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, int hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req80211, int chan_start, int chan_num); int hif_stop_scan(struct wfx_vif *wvif); -int hif_join(struct wfx_vif *wvif, const struct hif_req_join *arg); +int hif_join(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf, + const struct ieee80211_channel *channel, const u8 *ssidie); int hif_set_pm(struct wfx_vif *wvif, bool ps, int dynamic_ps_timeout); int hif_set_bss_params(struct wfx_vif *wvif, const struct hif_req_set_bss_params *arg); diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 395a282346b1..30c62e3b3716 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -512,32 +512,19 @@ static void wfx_set_mfp(struct wfx_vif *wvif, static void wfx_do_join(struct wfx_vif *wvif) { - const u8 *bssid; + int ret; + const u8 *ssidie; struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf; struct cfg80211_bss *bss = NULL; - struct hif_req_join join = { - .infrastructure_bss_mode = !conf->ibss_joined, - .short_preamble = conf->use_short_preamble, - .probe_for_join = 1, - .atim_window = 0, - .basic_rate_set = wfx_rate_mask_to_hw(wvif->wdev, - conf->basic_rates), - }; wfx_tx_lock_flush(wvif->wdev); - if (wvif->channel->flags & IEEE80211_CHAN_NO_IR) - join.probe_for_join = 0; - if (wvif->state) wfx_do_unjoin(wvif); - bssid = wvif->vif->bss_conf.bssid; - bss = cfg80211_get_bss(wvif->wdev->hw->wiphy, wvif->channel, - bssid, NULL, 0, + conf->bssid, NULL, 0, IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY); - if (!bss && !conf->ibss_joined) { wfx_tx_unlock(wvif->wdev); return; @@ -545,29 +532,15 @@ static void wfx_do_join(struct wfx_vif *wvif) mutex_lock(&wvif->wdev->conf_mutex); - /* Sanity check basic rates */ - if (!join.basic_rate_set) - join.basic_rate_set = 7; - /* Sanity check beacon interval */ if (!wvif->beacon_int) wvif->beacon_int = 1; - join.beacon_interval = wvif->beacon_int; - join.channel_number = wvif->channel->hw_value; - memcpy(join.bssid, bssid, sizeof(join.bssid)); - - if (!conf->ibss_joined) { - const u8 *ssidie; - - rcu_read_lock(); + rcu_read_lock(); + if (!conf->ibss_joined) ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); - if (ssidie) { - join.ssid_length = ssidie[1]; - memcpy(join.ssid, &ssidie[2], join.ssid_length); - } - rcu_read_unlock(); - } + else + ssidie = NULL; wfx_tx_flush(wvif->wdev); @@ -578,7 +551,9 @@ static void wfx_do_join(struct wfx_vif *wvif) /* Perform actual join */ wvif->wdev->tx_burst_idx = -1; - if (hif_join(wvif, &join)) { + ret = hif_join(wvif, conf, wvif->channel, ssidie); + rcu_read_unlock(); + if (ret) { ieee80211_connection_loss(wvif->vif); wvif->join_complete_status = -1; /* Tx lock still held, unjoin will clear it. */ From a8ec12d419af85c8225222ae19b26ea9c8fd6980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:46 +0000 Subject: [PATCH 273/353] staging: wfx: simplify hif_set_association_mode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structure hif_mib_set_association_mode come from hardware API. It is not intended to be manipulated in upper layers of the driver. In add, current code for hif_set_association_mode() is too dumb. It should pack data with hardware representation instead of leaving all work to the caller. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-31-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx_mib.h | 22 ++++++++++++++++++++-- drivers/staging/wfx/sta.c | 16 +--------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index 5b39200bd697..eec6f4157e60 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -191,10 +191,28 @@ static inline int hif_set_block_ack_policy(struct wfx_vif *wvif, } static inline int hif_set_association_mode(struct wfx_vif *wvif, - struct hif_mib_set_association_mode *arg) + struct ieee80211_bss_conf *info, + struct ieee80211_sta_ht_cap *ht_cap) { + int basic_rates = wfx_rate_mask_to_hw(wvif->wdev, info->basic_rates); + struct hif_mib_set_association_mode val = { + .preambtype_use = 1, + .mode = 1, + .rateset = 1, + .spacing = 1, + .short_preamble = info->use_short_preamble, + .basic_rate_set = cpu_to_le32(basic_rates) + }; + + // FIXME: it is strange to not retrieve all information from bss_info + if (ht_cap && ht_cap->ht_supported) { + val.mpdu_start_spacing = ht_cap->ampdu_density; + if (!(info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)) + val.greenfield = !!(ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD); + } + return hif_write_mib(wvif->wdev, wvif->id, - HIF_MIB_ID_SET_ASSOCIATION_MODE, arg, sizeof(*arg)); + HIF_MIB_ID_SET_ASSOCIATION_MODE, &val, sizeof(val)); } static inline int hif_set_tx_rate_retry_policy(struct wfx_vif *wvif, diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 30c62e3b3716..9030681858bb 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -712,7 +712,6 @@ static void wfx_join_finalize(struct wfx_vif *wvif, struct ieee80211_bss_conf *info) { struct ieee80211_sta *sta = NULL; - struct hif_mib_set_association_mode association_mode = { }; wvif->beacon_int = info->beacon_int; rcu_read_lock(); @@ -730,26 +729,13 @@ static void wfx_join_finalize(struct wfx_vif *wvif, else hif_dual_cts_protection(wvif, false); - association_mode.preambtype_use = 1; - association_mode.mode = 1; - association_mode.rateset = 1; - association_mode.spacing = 1; - association_mode.short_preamble = info->use_short_preamble; - association_mode.basic_rate_set = cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, info->basic_rates)); - if (sta && sta->ht_cap.ht_supported && - !(info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)) - association_mode.greenfield = - !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); - if (sta && sta->ht_cap.ht_supported) - association_mode.mpdu_start_spacing = sta->ht_cap.ampdu_density; - wfx_cqm_bssloss_sm(wvif, 0, 0, 0); cancel_work_sync(&wvif->unjoin_work); wvif->bss_params.beacon_lost_count = 20; wvif->bss_params.aid = info->aid; - hif_set_association_mode(wvif, &association_mode); + hif_set_association_mode(wvif, info, sta ? &sta->ht_cap : NULL); if (!info->ibss_joined) { hif_keep_alive_period(wvif, 30 /* sec */); From 46f044b965e62f07a9c1411328487bf8346dbc79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:48 +0000 Subject: [PATCH 274/353] staging: wfx: simplify hif_set_uc_mc_bc_condition() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structure hif_mib_uc_mc_bc_data_frame_condition come from hardware API. It is not intended to be manipulated in upper layers of the driver. In add, current code for hif_set_uc_mc_bc_condition() is too dumb. It should pack data with hardware representation instead of leaving all work to the caller. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-32-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx_mib.h | 14 +++++++++++--- drivers/staging/wfx/sta.c | 6 +----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index eec6f4157e60..4d171e6cfc9a 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -246,12 +246,20 @@ static inline int hif_set_mac_addr_condition(struct wfx_vif *wvif, arg, sizeof(*arg)); } -static inline int hif_set_uc_mc_bc_condition(struct wfx_vif *wvif, - struct hif_mib_uc_mc_bc_data_frame_condition *arg) +// FIXME: use a bitfield instead of 3 boolean values +static inline int hif_set_uc_mc_bc_condition(struct wfx_vif *wvif, int idx, + bool unic, bool multic, bool broadc) { + struct hif_mib_uc_mc_bc_data_frame_condition val = { + .condition_idx = idx, + .param.bits.type_unicast = unic, + .param.bits.type_multicast = multic, + .param.bits.type_broadcast = broadc, + }; + return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_UC_MC_BC_DATAFRAME_CONDITION, - arg, sizeof(*arg)); + &val, sizeof(val)); } static inline int hif_set_config_data_filter(struct wfx_vif *wvif, diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 9030681858bb..79285927c7bf 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -120,7 +120,6 @@ static int wfx_set_mcast_filter(struct wfx_vif *wvif, struct hif_mib_config_data_filter config = { }; struct hif_mib_set_data_filtering filter_data = { }; struct hif_mib_mac_addr_data_frame_condition filter_addr_val = { }; - struct hif_mib_uc_mc_bc_data_frame_condition filter_addr_type = { }; // Temporary workaround for filters return hif_set_data_filtering(wvif, &filter_data); @@ -144,10 +143,7 @@ static int wfx_set_mcast_filter(struct wfx_vif *wvif, } // Accept unicast and broadcast - filter_addr_type.condition_idx = 0; - filter_addr_type.param.bits.type_unicast = 1; - filter_addr_type.param.bits.type_broadcast = 1; - ret = hif_set_uc_mc_bc_condition(wvif, &filter_addr_type); + ret = hif_set_uc_mc_bc_condition(wvif, 0, true, false, true); if (ret) return ret; From f5864a1076d1a5f3c7d297ab79bfabaa69af3e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:49 +0000 Subject: [PATCH 275/353] staging: wfx: simplify hif_mib_uc_mc_bc_data_frame_condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current API defines bitfields. It is not very convenient. Prefer to use bitmasks. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-33-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_api_mib.h | 14 ++++---------- drivers/staging/wfx/hif_tx_mib.h | 9 +++------ drivers/staging/wfx/sta.c | 4 ++-- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/staging/wfx/hif_api_mib.h b/drivers/staging/wfx/hif_api_mib.h index 1603b3074bf7..e0ef0337e01c 100644 --- a/drivers/staging/wfx/hif_api_mib.h +++ b/drivers/staging/wfx/hif_api_mib.h @@ -181,19 +181,13 @@ struct hif_mib_ipv6_addr_data_frame_condition { u8 i_pv6_address[HIF_API_IPV6_ADDRESS_SIZE]; } __packed; -union hif_addr_type { - u8 value; - struct { - u8 type_unicast:1; - u8 type_multicast:1; - u8 type_broadcast:1; - u8 reserved:5; - } bits; -}; +#define HIF_FILTER_UNICAST 0x1 +#define HIF_FILTER_MULTICAST 0x2 +#define HIF_FILTER_BROADCAST 0x4 struct hif_mib_uc_mc_bc_data_frame_condition { u8 condition_idx; - union hif_addr_type param; + u8 allowed_frames; u8 reserved[2]; } __packed; diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index 4d171e6cfc9a..6e8b050cbc25 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -246,15 +246,12 @@ static inline int hif_set_mac_addr_condition(struct wfx_vif *wvif, arg, sizeof(*arg)); } -// FIXME: use a bitfield instead of 3 boolean values -static inline int hif_set_uc_mc_bc_condition(struct wfx_vif *wvif, int idx, - bool unic, bool multic, bool broadc) +static inline int hif_set_uc_mc_bc_condition(struct wfx_vif *wvif, + int idx, u8 allowed_frames) { struct hif_mib_uc_mc_bc_data_frame_condition val = { .condition_idx = idx, - .param.bits.type_unicast = unic, - .param.bits.type_multicast = multic, - .param.bits.type_broadcast = broadc, + .allowed_frames = allowed_frames, }; return hif_write_mib(wvif->wdev, wvif->id, diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 79285927c7bf..1c1b5a6c2474 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -142,8 +142,8 @@ static int wfx_set_mcast_filter(struct wfx_vif *wvif, config.mac_cond |= 1 << i; } - // Accept unicast and broadcast - ret = hif_set_uc_mc_bc_condition(wvif, 0, true, false, true); + ret = hif_set_uc_mc_bc_condition(wvif, 0, HIF_FILTER_UNICAST | + HIF_FILTER_BROADCAST); if (ret) return ret; From 3f5264e75c7bd332f38c8bc0f903771336fba44d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:51 +0000 Subject: [PATCH 276/353] staging: wfx: simplify hif_mib_set_data_filtering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The field "default_filter" was not obvious. In add, explicitly declare that fields default_filter and enable are booleans. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-34-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_api_mib.h | 8 +++++--- drivers/staging/wfx/sta.c | 3 +-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wfx/hif_api_mib.h b/drivers/staging/wfx/hif_api_mib.h index e0ef0337e01c..0c67cd4c1593 100644 --- a/drivers/staging/wfx/hif_api_mib.h +++ b/drivers/staging/wfx/hif_api_mib.h @@ -206,9 +206,11 @@ struct hif_mib_config_data_filter { } __packed; struct hif_mib_set_data_filtering { - u8 default_filter; - u8 enable; - u8 reserved[2]; + u8 invert_matching:1; + u8 reserved1:7; + u8 enable:1; + u8 reserved2:7; + u8 reserved3[2]; } __packed; enum hif_arp_ns_frame_treatment { diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 1c1b5a6c2474..27248ea62aea 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -154,9 +154,8 @@ static int wfx_set_mcast_filter(struct wfx_vif *wvif, if (ret) return ret; - // discard all data frames except match filter filter_data.enable = 1; - filter_data.default_filter = 1; // discard all + filter_data.invert_matching = 1; // discard all but matching frames ret = hif_set_data_filtering(wvif, &filter_data); return ret; From c47b70e2c5918fab8d100915b68ada8828563a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:52 +0000 Subject: [PATCH 277/353] staging: wfx: simplify hif_set_data_filtering() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structure hif_mib_set_data_filtering come from hardware API. It is not intended to be manipulated in upper layers of the driver. In add, current code for hif_set_data_filtering() is too dumb. It should pack data with hardware representation instead of leaving all work to the caller. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-35-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx_mib.h | 9 +++++++-- drivers/staging/wfx/sta.c | 13 ++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index 6e8b050cbc25..ee22c7169fab 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -267,10 +267,15 @@ static inline int hif_set_config_data_filter(struct wfx_vif *wvif, } static inline int hif_set_data_filtering(struct wfx_vif *wvif, - struct hif_mib_set_data_filtering *arg) + bool enable, bool invert) { + struct hif_mib_set_data_filtering val = { + .enable = enable, + .invert_matching = invert, + }; + return hif_write_mib(wvif->wdev, wvif->id, - HIF_MIB_ID_SET_DATA_FILTERING, arg, sizeof(*arg)); + HIF_MIB_ID_SET_DATA_FILTERING, &val, sizeof(val)); } static inline int hif_keep_alive_period(struct wfx_vif *wvif, int period) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 27248ea62aea..588094486a7a 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -118,16 +118,13 @@ static int wfx_set_mcast_filter(struct wfx_vif *wvif, { int i, ret; struct hif_mib_config_data_filter config = { }; - struct hif_mib_set_data_filtering filter_data = { }; struct hif_mib_mac_addr_data_frame_condition filter_addr_val = { }; // Temporary workaround for filters - return hif_set_data_filtering(wvif, &filter_data); + return hif_set_data_filtering(wvif, false, true); - if (!fp->enable) { - filter_data.enable = 0; - return hif_set_data_filtering(wvif, &filter_data); - } + if (!fp->enable) + return hif_set_data_filtering(wvif, false, true); // A1 Address match on list for (i = 0; i < fp->num_addresses; i++) { @@ -154,9 +151,7 @@ static int wfx_set_mcast_filter(struct wfx_vif *wvif, if (ret) return ret; - filter_data.enable = 1; - filter_data.invert_matching = 1; // discard all but matching frames - ret = hif_set_data_filtering(wvif, &filter_data); + ret = hif_set_data_filtering(wvif, true, true); return ret; } From a077126a20a49117903596ceccf0f21ed16b5841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:54 +0000 Subject: [PATCH 278/353] staging: wfx: simplify hif_set_mac_addr_condition() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structure hif_mib_mac_addr_data_frame_condition come from hardware API. It is not intended to be manipulated in upper layers of the driver. In add, current code for hif_set_mac_addr_condition() is too dumb. It should pack data with hardware representation instead of leaving all work to the caller. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-36-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx_mib.h | 10 ++++++++-- drivers/staging/wfx/sta.c | 9 +-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index ee22c7169fab..90474b1c5ec3 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -239,11 +239,17 @@ static inline int hif_set_tx_rate_retry_policy(struct wfx_vif *wvif, } static inline int hif_set_mac_addr_condition(struct wfx_vif *wvif, - struct hif_mib_mac_addr_data_frame_condition *arg) + int idx, const u8 *mac_addr) { + struct hif_mib_mac_addr_data_frame_condition val = { + .condition_idx = idx, + .address_type = HIF_MAC_ADDR_A1, + }; + + ether_addr_copy(val.mac_address, mac_addr); return hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_MAC_ADDR_DATAFRAME_CONDITION, - arg, sizeof(*arg)); + &val, sizeof(val)); } static inline int hif_set_uc_mc_bc_condition(struct wfx_vif *wvif, diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 588094486a7a..b74e0ce41069 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -118,7 +118,6 @@ static int wfx_set_mcast_filter(struct wfx_vif *wvif, { int i, ret; struct hif_mib_config_data_filter config = { }; - struct hif_mib_mac_addr_data_frame_condition filter_addr_val = { }; // Temporary workaround for filters return hif_set_data_filtering(wvif, false, true); @@ -126,14 +125,8 @@ static int wfx_set_mcast_filter(struct wfx_vif *wvif, if (!fp->enable) return hif_set_data_filtering(wvif, false, true); - // A1 Address match on list for (i = 0; i < fp->num_addresses; i++) { - filter_addr_val.condition_idx = i; - filter_addr_val.address_type = HIF_MAC_ADDR_A1; - ether_addr_copy(filter_addr_val.mac_address, - fp->address_list[i]); - ret = hif_set_mac_addr_condition(wvif, - &filter_addr_val); + ret = hif_set_mac_addr_condition(wvif, i, fp->address_list[i]); if (ret) return ret; config.mac_cond |= 1 << i; From db94907110eae5977015e3f12e71d3c07f0f3dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:55 +0000 Subject: [PATCH 279/353] staging: wfx: simplify hif_set_config_data_filter() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structure hif_mib_config_data_filter come from hardware API. It is not intended to be manipulated in upper layers of the driver. In add, current code for hif_set_config_data_filter() is too dumb. It should pack data with hardware representation instead of leaving all work to the caller. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-37-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx_mib.h | 14 +++++++++++--- drivers/staging/wfx/sta.c | 8 ++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index 90474b1c5ec3..ccea3f15a34d 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -265,11 +265,19 @@ static inline int hif_set_uc_mc_bc_condition(struct wfx_vif *wvif, &val, sizeof(val)); } -static inline int hif_set_config_data_filter(struct wfx_vif *wvif, - struct hif_mib_config_data_filter *arg) +static inline int hif_set_config_data_filter(struct wfx_vif *wvif, bool enable, + int idx, int mac_filters, + int frames_types_filters) { + struct hif_mib_config_data_filter val = { + .enable = enable, + .filter_idx = idx, + .mac_cond = mac_filters, + .uc_mc_bc_cond = frames_types_filters, + }; + return hif_write_mib(wvif->wdev, wvif->id, - HIF_MIB_ID_CONFIG_DATA_FILTER, arg, sizeof(*arg)); + HIF_MIB_ID_CONFIG_DATA_FILTER, &val, sizeof(val)); } static inline int hif_set_data_filtering(struct wfx_vif *wvif, diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index b74e0ce41069..e71b99aa1f63 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -117,7 +117,6 @@ static int wfx_set_mcast_filter(struct wfx_vif *wvif, struct wfx_grp_addr_table *fp) { int i, ret; - struct hif_mib_config_data_filter config = { }; // Temporary workaround for filters return hif_set_data_filtering(wvif, false, true); @@ -129,7 +128,6 @@ static int wfx_set_mcast_filter(struct wfx_vif *wvif, ret = hif_set_mac_addr_condition(wvif, i, fp->address_list[i]); if (ret) return ret; - config.mac_cond |= 1 << i; } ret = hif_set_uc_mc_bc_condition(wvif, 0, HIF_FILTER_UNICAST | @@ -137,10 +135,8 @@ static int wfx_set_mcast_filter(struct wfx_vif *wvif, if (ret) return ret; - config.uc_mc_bc_cond = 1; - config.filter_idx = 0; // TODO #define MULTICAST_FILTERING 0 - config.enable = 1; - ret = hif_set_config_data_filter(wvif, &config); + ret = hif_set_config_data_filter(wvif, true, 0, BIT(1), + BIT(fp->num_addresses) - 1); if (ret) return ret; From 0b58486e153c12845b1f55e0ac458a2cd777ffb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:56 +0000 Subject: [PATCH 280/353] staging: wfx: simplify wfx_set_mcast_filter() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HIF functions return only serious errors (OOM or device freeze). The current handling of errors in wfx_set_mcast_filter() does not bring anything. Finally it may disturb the developer more than it helps. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-38-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index e71b99aa1f63..a934f66f3a4c 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -116,7 +116,7 @@ int wfx_fwd_probe_req(struct wfx_vif *wvif, bool enable) static int wfx_set_mcast_filter(struct wfx_vif *wvif, struct wfx_grp_addr_table *fp) { - int i, ret; + int i; // Temporary workaround for filters return hif_set_data_filtering(wvif, false, true); @@ -124,25 +124,15 @@ static int wfx_set_mcast_filter(struct wfx_vif *wvif, if (!fp->enable) return hif_set_data_filtering(wvif, false, true); - for (i = 0; i < fp->num_addresses; i++) { - ret = hif_set_mac_addr_condition(wvif, i, fp->address_list[i]); - if (ret) - return ret; - } + for (i = 0; i < fp->num_addresses; i++) + hif_set_mac_addr_condition(wvif, i, fp->address_list[i]); + hif_set_uc_mc_bc_condition(wvif, 0, + HIF_FILTER_UNICAST | HIF_FILTER_BROADCAST); + hif_set_config_data_filter(wvif, true, 0, BIT(1), + BIT(fp->num_addresses) - 1); + hif_set_data_filtering(wvif, true, true); - ret = hif_set_uc_mc_bc_condition(wvif, 0, HIF_FILTER_UNICAST | - HIF_FILTER_BROADCAST); - if (ret) - return ret; - - ret = hif_set_config_data_filter(wvif, true, 0, BIT(1), - BIT(fp->num_addresses) - 1); - if (ret) - return ret; - - ret = hif_set_data_filtering(wvif, true, true); - - return ret; + return 0; } void wfx_update_filtering(struct wfx_vif *wvif) From fd5d78bdf7527bb4c8739dc7d56b5b9a669d592b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:58 +0000 Subject: [PATCH 281/353] staging: wfx: simplify wfx_update_filtering() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wfx_update_filtering() has no reason to instantiate a struct hif_mib_bcn_filter_enable. Drop it and simplify the code. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-39-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index a934f66f3a4c..0c3150a94c7c 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -138,10 +138,9 @@ static int wfx_set_mcast_filter(struct wfx_vif *wvif, void wfx_update_filtering(struct wfx_vif *wvif) { int ret; - bool is_sta = wvif->vif && NL80211_IFTYPE_STATION == wvif->vif->type; - bool filter_bssid = wvif->filter_bssid; - bool fwd_probe_req = wvif->fwd_probe_req; - struct hif_mib_bcn_filter_enable bf_ctrl; + int bf_enable; + int bf_count; + int n_filter_ies; struct hif_ie_table_entry filter_ies[] = { { .ie_id = WLAN_EID_VENDOR_SPECIFIC, @@ -161,33 +160,29 @@ void wfx_update_filtering(struct wfx_vif *wvif) .has_appeared = 1, } }; - int n_filter_ies; if (wvif->state == WFX_STATE_PASSIVE) return; if (wvif->disable_beacon_filter) { - bf_ctrl.enable = 0; - bf_ctrl.bcn_count = 1; + bf_enable = 0; + bf_count = 1; n_filter_ies = 0; - } else if (!is_sta) { - bf_ctrl.enable = HIF_BEACON_FILTER_ENABLE | - HIF_BEACON_FILTER_AUTO_ERP; - bf_ctrl.bcn_count = 0; + } else if (wvif->vif->type != NL80211_IFTYPE_STATION) { + bf_enable = HIF_BEACON_FILTER_ENABLE | HIF_BEACON_FILTER_AUTO_ERP; + bf_count = 0; n_filter_ies = 2; } else { - bf_ctrl.enable = HIF_BEACON_FILTER_ENABLE; - bf_ctrl.bcn_count = 0; + bf_enable = HIF_BEACON_FILTER_ENABLE; + bf_count = 0; n_filter_ies = 3; } - ret = hif_set_rx_filter(wvif, filter_bssid, fwd_probe_req); + ret = hif_set_rx_filter(wvif, wvif->filter_bssid, wvif->fwd_probe_req); if (!ret) - ret = hif_set_beacon_filter_table(wvif, n_filter_ies, - filter_ies); + ret = hif_set_beacon_filter_table(wvif, n_filter_ies, filter_ies); if (!ret) - ret = hif_beacon_filter_control(wvif, bf_ctrl.enable, - bf_ctrl.bcn_count); + ret = hif_beacon_filter_control(wvif, bf_enable, bf_count); if (!ret) ret = wfx_set_mcast_filter(wvif, &wvif->mcast_filter); if (ret) From 7f091d319eb54adc597cdb8db906d5835a611665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:54:59 +0000 Subject: [PATCH 282/353] staging: wfx: simplify wfx_scan_complete() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wfx_scan_complete() do nothing with argument hif_ind_scan_cmpl. In add, hif_ind_scan_cmpl come from hardware API and is not expected to be used with upper layers of the driver. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-40-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_rx.c | 3 +-- drivers/staging/wfx/scan.c | 3 +-- drivers/staging/wfx/scan.h | 5 +---- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/staging/wfx/hif_rx.c b/drivers/staging/wfx/hif_rx.c index 408967a4c457..f04afc6db9a5 100644 --- a/drivers/staging/wfx/hif_rx.c +++ b/drivers/staging/wfx/hif_rx.c @@ -203,10 +203,9 @@ static int hif_scan_complete_indication(struct wfx_dev *wdev, const void *buf) { struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); - const struct hif_ind_scan_cmpl *body = buf; WARN_ON(!wvif); - wfx_scan_complete(wvif, body); + wfx_scan_complete(wvif); return 0; } diff --git a/drivers/staging/wfx/scan.c b/drivers/staging/wfx/scan.c index 5cc9df5eb6a1..6e1e50048651 100644 --- a/drivers/staging/wfx/scan.c +++ b/drivers/staging/wfx/scan.c @@ -127,8 +127,7 @@ void wfx_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) hif_stop_scan(wvif); } -void wfx_scan_complete(struct wfx_vif *wvif, - const struct hif_ind_scan_cmpl *arg) +void wfx_scan_complete(struct wfx_vif *wvif) { complete(&wvif->scan_complete); } diff --git a/drivers/staging/wfx/scan.h b/drivers/staging/wfx/scan.h index bba9f15a9ff5..2eb786c9572c 100644 --- a/drivers/staging/wfx/scan.h +++ b/drivers/staging/wfx/scan.h @@ -10,8 +10,6 @@ #include -#include "hif_api_cmd.h" - struct wfx_dev; struct wfx_vif; @@ -19,7 +17,6 @@ void wfx_hw_scan_work(struct work_struct *work); int wfx_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *req); void wfx_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -void wfx_scan_complete(struct wfx_vif *wvif, - const struct hif_ind_scan_cmpl *ind); +void wfx_scan_complete(struct wfx_vif *wvif); #endif /* WFX_SCAN_H */ From 8d97a12fa4d25f72394201ec840d9231b76b101f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:01 +0000 Subject: [PATCH 283/353] staging: wfx: update power-save per interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mac80211 and the device are both able to control power-save per vif. But, the current code retrieve power-save from wfx_config(). So, it does not allow to setup power-save independently for each vif. Driver just has to rely on wfx_bss_info_changed() instead of wfx_config(). wfx_config() has nothing to do anymore, but we keep it since it is mandatory for mac80211. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-41-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/main.c | 2 +- drivers/staging/wfx/sta.c | 17 +++++------------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/staging/wfx/main.c b/drivers/staging/wfx/main.c index 1904890c03fe..84adad64fc30 100644 --- a/drivers/staging/wfx/main.c +++ b/drivers/staging/wfx/main.c @@ -131,7 +131,7 @@ static const struct ieee80211_ops wfx_ops = { .stop = wfx_stop, .add_interface = wfx_add_interface, .remove_interface = wfx_remove_interface, - .config = wfx_config, + .config = wfx_config, .tx = wfx_tx, .conf_tx = wfx_conf_tx, .hw_scan = wfx_hw_scan, diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 0c3150a94c7c..94683a1440c8 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -826,6 +826,10 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_TXPOWER) hif_set_output_power(wvif, info->txpower); + + if (changed & BSS_CHANGED_PS) + wfx_update_pm(wvif); + mutex_unlock(&wdev->conf_mutex); if (do_join) @@ -1058,18 +1062,7 @@ void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw, int wfx_config(struct ieee80211_hw *hw, u32 changed) { - int ret = 0; - struct wfx_dev *wdev = hw->priv; - struct wfx_vif *wvif; - - if (changed & IEEE80211_CONF_CHANGE_PS) { - mutex_lock(&wdev->conf_mutex); - wvif = NULL; - while ((wvif = wvif_iterate(wdev, wvif)) != NULL) - ret = wfx_update_pm(wvif); - mutex_unlock(&wdev->conf_mutex); - } - return ret; + return 0; } int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) From f98138a16f854889ef8f583c704d46d5b46161ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:02 +0000 Subject: [PATCH 284/353] staging: wfx: with multiple vifs, force PS only if channels differs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When multiple vif are in use (the only supported configuration is one station and one AP), the driver force power save flag on station. This behavior allows the station to leave the station channel and make its business on AP channel. However, this has a big impact on station performances (especially since only legacy PS is supported). When both vifs use the same channel, it is not necessary to keep this restriction. This greatly improve station performances. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-42-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 94683a1440c8..bf285389c303 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -251,6 +251,7 @@ static int wfx_update_pm(struct wfx_vif *wvif) struct ieee80211_conf *conf = &wvif->wdev->hw->conf; bool ps = conf->flags & IEEE80211_CONF_PS; int ps_timeout = conf->dynamic_ps_timeout; + struct ieee80211_channel *chan0 = NULL, *chan1 = NULL; WARN_ON(conf->dynamic_ps_timeout < 0); if (wvif->state != WFX_STATE_STA || !wvif->bss_params.aid) @@ -260,10 +261,15 @@ static int wfx_update_pm(struct wfx_vif *wvif) if (wvif->uapsd_mask) ps_timeout = 0; - // Kernel disable PowerSave when multiple vifs are in use. In contrary, - // it is absolutly necessary to enable PowerSave for WF200 - // FIXME: only if channel vif0 != channel vif1 - if (wvif_count(wvif->wdev) > 1) { + // Kernel disable powersave when an AP is in use. In contrary, it is + // absolutely necessary to enable legacy powersave for WF200 if channels + // are differents. + if (wdev_to_wvif(wvif->wdev, 0)) + chan0 = wdev_to_wvif(wvif->wdev, 0)->vif->bss_conf.chandef.chan; + if (wdev_to_wvif(wvif->wdev, 1)) + chan1 = wdev_to_wvif(wvif->wdev, 1)->vif->bss_conf.chandef.chan; + if (chan0 && chan1 && chan0->hw_value != chan1->hw_value && + wvif->vif->type != NL80211_IFTYPE_AP) { ps = true; ps_timeout = 0; } From 9b90910f5bf4d6c76bbd55fcda5baa0ff015060b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:03 +0000 Subject: [PATCH 285/353] staging: wfx: do not update uapsd if not necessary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wfx_conf_tx() is called for each queue. On every call, the function updates UAPSD mask and PM mode for all queues. It is a pity since the UAPSD configuration very rarely changes and it makes exchanges between the host and the chip more difficult to track. This patch avoid to update UAPSD and Power Mode in most usual cases. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-43-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index bf285389c303..6a43decd5ae6 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -286,6 +286,7 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; + int old_uapsd = wvif->uapsd_mask; int ret = 0; WARN_ON(queue >= hw->queues); @@ -294,7 +295,8 @@ int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, assign_bit(queue, &wvif->uapsd_mask, params->uapsd); memcpy(&wvif->edca_params[queue], params, sizeof(*params)); hif_set_edca_queue_params(wvif, queue, params); - if (wvif->vif->type == NL80211_IFTYPE_STATION) { + if (wvif->vif->type == NL80211_IFTYPE_STATION && + old_uapsd != wvif->uapsd_mask) { hif_set_uapsd_info(wvif, wvif->uapsd_mask); wfx_update_pm(wvif); } From 4e1514c940fc64e7fb922a9390742f8e28a460ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:05 +0000 Subject: [PATCH 286/353] staging: wfx: fix case where RTS threshold is 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If RTS threshold is 0, it currently disables RTS. It should mean "enabled for every frames". Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-44-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_tx_mib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wfx/hif_tx_mib.h b/drivers/staging/wfx/hif_tx_mib.h index ccea3f15a34d..bf3769c2a9b6 100644 --- a/drivers/staging/wfx/hif_tx_mib.h +++ b/drivers/staging/wfx/hif_tx_mib.h @@ -391,7 +391,7 @@ static inline int hif_wep_default_key_id(struct wfx_vif *wvif, int val) static inline int hif_rts_threshold(struct wfx_vif *wvif, int val) { struct hif_mib_dot11_rts_threshold arg = { - .threshold = cpu_to_le32(val > 0 ? val : 0xFFFF), + .threshold = cpu_to_le32(val >= 0 ? val : 0xFFFF), }; return hif_write_mib(wvif->wdev, wvif->id, From def39be019b6494acd3570ce6f3f11ba1c3203a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:06 +0000 Subject: [PATCH 287/353] staging: wfx: fix possible overflow on jiffies comparaison MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is recommended to use function time_*() to compare jiffies. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-45-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index 60459299a3a9..704ebfe1cd05 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -270,8 +270,7 @@ void wfx_tx_policy_init(struct wfx_vif *wvif) static int wfx_alloc_link_id(struct wfx_vif *wvif, const u8 *mac) { int i, ret = 0; - unsigned long max_inactivity = 0; - unsigned long now = jiffies; + unsigned long oldest; spin_lock_bh(&wvif->ps_state_lock); for (i = 0; i < WFX_MAX_STA_IN_AP_MODE; ++i) { @@ -280,13 +279,10 @@ static int wfx_alloc_link_id(struct wfx_vif *wvif, const u8 *mac) break; } else if (wvif->link_id_db[i].status != WFX_LINK_HARD && !wvif->wdev->tx_queue_stats.link_map_cache[i + 1]) { - unsigned long inactivity = - now - wvif->link_id_db[i].timestamp; - - if (inactivity < max_inactivity) - continue; - max_inactivity = inactivity; - ret = i + 1; + if (!ret || time_after(oldest, wvif->link_id_db[i].timestamp)) { + oldest = wvif->link_id_db[i].timestamp; + ret = i + 1; + } } } From 79d5fecc9be29b3159d9d6204082080922e8419f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:08 +0000 Subject: [PATCH 288/353] staging: wfx: remove handling of "early_data" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems that purpose of "early_data" was to prevent sending data to mac80211 before station was completely associated. It is a useless precaution. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-46-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_rx.c | 17 +---------------- drivers/staging/wfx/data_tx.c | 3 --- drivers/staging/wfx/data_tx.h | 1 - drivers/staging/wfx/sta.c | 3 --- 4 files changed, 1 insertion(+), 23 deletions(-) diff --git a/drivers/staging/wfx/data_rx.c b/drivers/staging/wfx/data_rx.c index 0ab71c911f84..e26bc665b2b3 100644 --- a/drivers/staging/wfx/data_rx.c +++ b/drivers/staging/wfx/data_rx.c @@ -108,7 +108,6 @@ void wfx_rx_cb(struct wfx_vif *wvif, struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; struct wfx_link_entry *entry = NULL; - bool early_data = false; memset(hdr, 0, sizeof(*hdr)); @@ -121,9 +120,6 @@ void wfx_rx_cb(struct wfx_vif *wvif, if (link_id && link_id <= WFX_MAX_STA_IN_AP_MODE) { entry = &wvif->link_id_db[link_id - 1]; entry->timestamp = jiffies; - if (entry->status == WFX_LINK_SOFT && - ieee80211_is_data(frame->frame_control)) - early_data = true; } if (arg->status == HIF_STATUS_MICFAILURE) @@ -181,18 +177,7 @@ void wfx_rx_cb(struct wfx_vif *wvif, schedule_work(&wvif->update_filtering_work); } } - - if (early_data) { - spin_lock_bh(&wvif->ps_state_lock); - /* Double-check status with lock held */ - if (entry->status == WFX_LINK_SOFT) - skb_queue_tail(&entry->rx_queue, skb); - else - ieee80211_rx_irqsafe(wvif->wdev->hw, skb); - spin_unlock_bh(&wvif->ps_state_lock); - } else { - ieee80211_rx_irqsafe(wvif->wdev->hw, skb); - } + ieee80211_rx_irqsafe(wvif->wdev->hw, skb); return; diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index 704ebfe1cd05..e669fc4485e6 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -292,7 +292,6 @@ static int wfx_alloc_link_id(struct wfx_vif *wvif, const u8 *mac) entry->status = WFX_LINK_RESERVE; ether_addr_copy(entry->mac, mac); memset(&entry->buffered, 0, WFX_MAX_TID); - skb_queue_head_init(&entry->rx_queue); wfx_tx_lock(wvif->wdev); if (!schedule_work(&wvif->link_id_work)) @@ -400,8 +399,6 @@ void wfx_link_id_gc_work(struct work_struct *work) next_gc = min_t(unsigned long, next_gc, ttl); } } - if (need_reset) - skb_queue_purge(&wvif->link_id_db[i].rx_queue); } spin_unlock_bh(&wvif->ps_state_lock); if (next_gc != -1) diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h index 078d0cfc521a..54738c2e3eac 100644 --- a/drivers/staging/wfx/data_tx.h +++ b/drivers/staging/wfx/data_tx.h @@ -34,7 +34,6 @@ struct wfx_link_entry { u8 mac[ETH_ALEN]; u8 old_mac[ETH_ALEN]; u8 buffered[WFX_MAX_TID]; - struct sk_buff_head rx_queue; }; struct tx_policy { diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 6a43decd5ae6..4a44d72f0db1 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -571,7 +571,6 @@ int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv; struct wfx_link_entry *entry; - struct sk_buff *skb; if (wvif->vif->type != NL80211_IFTYPE_AP) return 0; @@ -589,8 +588,6 @@ int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) wvif->sta_asleep_mask |= BIT(sta_priv->link_id); entry->status = WFX_LINK_HARD; - while ((skb = skb_dequeue(&entry->rx_queue))) - ieee80211_rx_irqsafe(wdev->hw, skb); spin_unlock_bh(&wvif->ps_state_lock); return 0; } From 7d2d2bfdeb82c383f5cd8b93b1c234249c1a588c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:09 +0000 Subject: [PATCH 289/353] staging: wfx: relocate "buffered" information to sta_priv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It simplify the code if field buffered is hosted in the struct sta_priv instead of in the struct wfx_link_entry. More globally, struct wfx_link_entry has no real reasons to exist and should be dropped soon. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-47-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 50 ++++++++++++++++------------------- drivers/staging/wfx/data_tx.h | 4 --- drivers/staging/wfx/sta.c | 1 + drivers/staging/wfx/sta.h | 6 +++++ 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index e669fc4485e6..9313c8f5d4d8 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -291,7 +291,6 @@ static int wfx_alloc_link_id(struct wfx_vif *wvif, const u8 *mac) entry->status = WFX_LINK_RESERVE; ether_addr_copy(entry->mac, mac); - memset(&entry->buffered, 0, WFX_MAX_TID); wfx_tx_lock(wvif->wdev); if (!schedule_work(&wvif->link_id_work)) @@ -434,6 +433,7 @@ static void wfx_tx_manage_pm(struct wfx_vif *wvif, struct ieee80211_hdr *hdr, struct ieee80211_sta *sta) { u32 mask = ~BIT(tx_priv->raw_link_id); + struct wfx_sta_priv *sta_priv; spin_lock_bh(&wvif->ps_state_lock); if (ieee80211_is_auth(hdr->frame_control)) { @@ -448,15 +448,17 @@ static void wfx_tx_manage_pm(struct wfx_vif *wvif, struct ieee80211_hdr *hdr, schedule_work(&wvif->mcast_start_work); } - if (tx_priv->raw_link_id) { + if (tx_priv->raw_link_id) wvif->link_id_db[tx_priv->raw_link_id - 1].timestamp = jiffies; - if (tx_priv->tid < WFX_MAX_TID) - wvif->link_id_db[tx_priv->raw_link_id - 1].buffered[tx_priv->tid]++; - } spin_unlock_bh(&wvif->ps_state_lock); - if (sta) + if (sta && tx_priv->tid < WFX_MAX_TID) { + sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; + spin_lock_bh(&sta_priv->lock); + sta_priv->buffered[tx_priv->tid]++; ieee80211_sta_set_buffered(sta, tx_priv->tid, true); + spin_unlock_bh(&sta_priv->lock); + } } static u8 wfx_tx_get_raw_link_id(struct wfx_vif *wvif, @@ -789,31 +791,25 @@ void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg) wfx_pending_remove(wvif->wdev, skb); } -static void wfx_notify_buffered_tx(struct wfx_vif *wvif, struct sk_buff *skb, - struct hif_req_tx *req) +static void wfx_notify_buffered_tx(struct wfx_vif *wvif, struct sk_buff *skb) { - struct ieee80211_sta *sta; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_sta *sta; + struct wfx_sta_priv *sta_priv; int tid = wfx_tx_get_tid(hdr); - int raw_link_id = req->queue_id.peer_sta_id; - u8 *buffered; - if (raw_link_id && tid < WFX_MAX_TID) { - buffered = wvif->link_id_db[raw_link_id - 1].buffered; - - spin_lock_bh(&wvif->ps_state_lock); - WARN(!buffered[tid], "inconsistent notification"); - buffered[tid]--; - spin_unlock_bh(&wvif->ps_state_lock); - - if (!buffered[tid]) { - rcu_read_lock(); - sta = ieee80211_find_sta(wvif->vif, hdr->addr1); - if (sta) - ieee80211_sta_set_buffered(sta, tid, false); - rcu_read_unlock(); - } + rcu_read_lock(); // protect sta + sta = ieee80211_find_sta(wvif->vif, hdr->addr1); + if (sta && tid < WFX_MAX_TID) { + sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; + spin_lock_bh(&sta_priv->lock); + WARN(!sta_priv->buffered[tid], "inconsistent notification"); + sta_priv->buffered[tid]--; + if (!sta_priv->buffered[tid]) + ieee80211_sta_set_buffered(sta, tid, false); + spin_unlock_bh(&sta_priv->lock); } + rcu_read_unlock(); } void wfx_skb_dtor(struct wfx_dev *wdev, struct sk_buff *skb) @@ -827,7 +823,7 @@ void wfx_skb_dtor(struct wfx_dev *wdev, struct sk_buff *skb) WARN_ON(!wvif); skb_pull(skb, offset); - wfx_notify_buffered_tx(wvif, skb, req); + wfx_notify_buffered_tx(wvif, skb); wfx_tx_policy_put(wvif, req->tx_flags.retry_policy_index); ieee80211_tx_status_irqsafe(wdev->hw, skb); } diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h index 54738c2e3eac..d02a7b325b27 100644 --- a/drivers/staging/wfx/data_tx.h +++ b/drivers/staging/wfx/data_tx.h @@ -14,9 +14,6 @@ #include "hif_api_cmd.h" #include "hif_api_mib.h" -// FIXME: use IEEE80211_NUM_TIDS -#define WFX_MAX_TID 8 - struct wfx_tx_priv; struct wfx_dev; struct wfx_vif; @@ -33,7 +30,6 @@ struct wfx_link_entry { enum wfx_link_status status; u8 mac[ETH_ALEN]; u8 old_mac[ETH_ALEN]; - u8 buffered[WFX_MAX_TID]; }; struct tx_policy { diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 4a44d72f0db1..aebce96dcd4a 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -572,6 +572,7 @@ int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv; struct wfx_link_entry *entry; + spin_lock_init(&sta_priv->lock); if (wvif->vif->type != NL80211_IFTYPE_AP) return 0; diff --git a/drivers/staging/wfx/sta.h b/drivers/staging/wfx/sta.h index e0b54332e98a..47d94d6b8590 100644 --- a/drivers/staging/wfx/sta.h +++ b/drivers/staging/wfx/sta.h @@ -12,6 +12,9 @@ #include "hif_api_cmd.h" +// FIXME: use IEEE80211_NUM_TIDS +#define WFX_MAX_TID 8 + struct wfx_dev; struct wfx_vif; @@ -37,6 +40,9 @@ struct wfx_grp_addr_table { struct wfx_sta_priv { int link_id; int vif_id; + u8 buffered[WFX_MAX_TID]; + // Ensure atomicity of "buffered" and calls to ieee80211_sta_set_buffered() + spinlock_t lock; }; // mac80211 interface From 76b5c2ce468fc7fa5f4daf727bbefa6f8a2d7a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:10 +0000 Subject: [PATCH 290/353] staging: wfx: fix bss_loss MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wfx_tx_confirm_cb() retrieves the station associated with a frame using the MAC address from the 802.11 header. In the other side wfx_tx() retrieves the station using sta field from the ieee80211_tx_control argument. In wfx_cqm_bssloss_sm(), wfx_tx() was called directly without valid sta field, but with a valid MAC address in 802.11 header. So there the processing of this packet was unbalanced and may produce weird bugs. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-48-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index aebce96dcd4a..1c10ebd11944 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -88,19 +88,25 @@ void wfx_cqm_bssloss_sm(struct wfx_vif *wvif, int init, int good, int bad) // FIXME: call ieee80211_beacon_loss/ieee80211_connection_loss instead if (tx) { struct sk_buff *skb; + struct ieee80211_hdr *hdr; + struct ieee80211_tx_control control = { }; wvif->bss_loss_state++; skb = ieee80211_nullfunc_get(wvif->wdev->hw, wvif->vif, false); if (!skb) goto end; + hdr = (struct ieee80211_hdr *)skb->data; memset(IEEE80211_SKB_CB(skb), 0, sizeof(*IEEE80211_SKB_CB(skb))); IEEE80211_SKB_CB(skb)->control.vif = wvif->vif; IEEE80211_SKB_CB(skb)->driver_rates[0].idx = 0; IEEE80211_SKB_CB(skb)->driver_rates[0].count = 1; IEEE80211_SKB_CB(skb)->driver_rates[1].idx = -1; - wfx_tx(wvif->wdev->hw, NULL, skb); + rcu_read_lock(); // protect control.sta + control.sta = ieee80211_find_sta(wvif->vif, hdr->addr1); + wfx_tx(wvif->wdev->hw, &control, skb); + rcu_read_unlock(); } end: mutex_unlock(&wvif->bss_loss_lock); From d00149011066bde86cd56c64b77616c40a4f83af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:12 +0000 Subject: [PATCH 291/353] staging: wfx: fix RCU usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Indeed, sta was used after call to rcu_unlock() Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-49-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 1c10ebd11944..cc72877a090f 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -690,10 +690,9 @@ static void wfx_join_finalize(struct wfx_vif *wvif, struct ieee80211_sta *sta = NULL; wvif->beacon_int = info->beacon_int; - rcu_read_lock(); + rcu_read_lock(); // protect sta if (info->bssid && !info->ibss_joined) sta = ieee80211_find_sta(wvif->vif, info->bssid); - rcu_read_unlock(); if (sta) wvif->bss_params.operational_rate_set = wfx_rate_mask_to_hw(wvif->wdev, sta->supp_rates[wvif->channel->band]); @@ -712,6 +711,7 @@ static void wfx_join_finalize(struct wfx_vif *wvif, wvif->bss_params.aid = info->aid; hif_set_association_mode(wvif, info, sta ? &sta->ht_cap : NULL); + rcu_read_unlock(); if (!info->ibss_joined) { hif_keep_alive_period(wvif, 30 /* sec */); From 36cbb5d2a7db063879fc92e8496db9c0b7f84d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:13 +0000 Subject: [PATCH 292/353] staging: wfx: simplify wfx_set_tim_impl() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Argument provided to wfx_set_tim_impl() is always wvif->aid0_bit_set and there is no reason to provide another argument. Also rename wfx_set_tim_impl() into wfx_update_tim() to reflect the new behavior. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-50-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 18 +++++++++--------- drivers/staging/wfx/wfx.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index cc72877a090f..b7d21540d9a2 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -895,7 +895,7 @@ void wfx_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, wfx_ps_notify(wvif, notify_cmd, sta_priv->link_id); } -static int wfx_set_tim_impl(struct wfx_vif *wvif, bool aid0_bit_set) +static int wfx_update_tim(struct wfx_vif *wvif) { struct sk_buff *skb; u16 tim_offset, tim_length; @@ -916,7 +916,7 @@ static int wfx_set_tim_impl(struct wfx_vif *wvif, bool aid0_bit_set) tim_ptr[2] = 0; /* Set/reset aid0 bit */ - if (aid0_bit_set) + if (wvif->aid0_bit_set) tim_ptr[4] |= 1; else tim_ptr[4] &= ~1; @@ -928,11 +928,11 @@ static int wfx_set_tim_impl(struct wfx_vif *wvif, bool aid0_bit_set) return 0; } -static void wfx_set_tim_work(struct work_struct *work) +static void wfx_update_tim_work(struct work_struct *work) { - struct wfx_vif *wvif = container_of(work, struct wfx_vif, set_tim_work); + struct wfx_vif *wvif = container_of(work, struct wfx_vif, update_tim_work); - wfx_set_tim_impl(wvif, wvif->aid0_bit_set); + wfx_update_tim(wvif); } int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) @@ -941,7 +941,7 @@ int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) struct wfx_sta_priv *sta_dev = (struct wfx_sta_priv *) &sta->drv_priv; struct wfx_vif *wvif = wdev_to_wvif(wdev, sta_dev->vif_id); - schedule_work(&wvif->set_tim_work); + schedule_work(&wvif->update_tim_work); return 0; } @@ -955,8 +955,8 @@ static void wfx_mcast_start_work(struct work_struct *work) cancel_work_sync(&wvif->mcast_stop_work); if (!wvif->aid0_bit_set) { wfx_tx_lock_flush(wvif->wdev); - wfx_set_tim_impl(wvif, true); wvif->aid0_bit_set = true; + wfx_update_tim(wvif); mod_timer(&wvif->mcast_timeout, jiffies + tmo); wfx_tx_unlock(wvif->wdev); } @@ -971,7 +971,7 @@ static void wfx_mcast_stop_work(struct work_struct *work) del_timer_sync(&wvif->mcast_timeout); wfx_tx_lock_flush(wvif->wdev); wvif->aid0_bit_set = false; - wfx_set_tim_impl(wvif, false); + wfx_update_tim(wvif); wfx_tx_unlock(wvif->wdev); } } @@ -1118,7 +1118,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) INIT_DELAYED_WORK(&wvif->link_id_gc_work, wfx_link_id_gc_work); spin_lock_init(&wvif->ps_state_lock); - INIT_WORK(&wvif->set_tim_work, wfx_set_tim_work); + INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work); INIT_WORK(&wvif->mcast_start_work, wfx_mcast_start_work); INIT_WORK(&wvif->mcast_stop_work, wfx_mcast_stop_work); diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index f56a91ea082d..cb359150e2ad 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -96,7 +96,7 @@ struct wfx_vif { u32 sta_asleep_mask; u32 pspoll_mask; spinlock_t ps_state_lock; - struct work_struct set_tim_work; + struct work_struct update_tim_work; int beacon_int; bool filter_bssid; From d6aeba575f277104a95125584981d37c8f7cf762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:15 +0000 Subject: [PATCH 293/353] staging: wfx: simplify the link-id allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "link-id" is a slot number provided to the chip. A link-id is allocated to every station associated with the chip (mainly when the chip is in AP mode). It is more or less the same thing than the association ID, but it is limited to 14 values. Firmware uses the link-id to track the power save status of the stations. The current code try to associate a link-id as soon as data are exchanged with station. It is far easier to rely on sta_add() and sta_remove(). Until now the value WFX_LINK_ID_NO_ASSOC, was only used when no more link-id was available. Now, we also use this value for not-yet-associated stations (that was its primary behavior). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-51-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_rx.c | 7 -- drivers/staging/wfx/data_tx.c | 164 +--------------------------------- drivers/staging/wfx/data_tx.h | 19 ---- drivers/staging/wfx/queue.c | 7 +- drivers/staging/wfx/queue.h | 7 +- drivers/staging/wfx/sta.c | 58 ++++-------- drivers/staging/wfx/wfx.h | 3 - 7 files changed, 24 insertions(+), 241 deletions(-) diff --git a/drivers/staging/wfx/data_rx.c b/drivers/staging/wfx/data_rx.c index e26bc665b2b3..699e2d60fa89 100644 --- a/drivers/staging/wfx/data_rx.c +++ b/drivers/staging/wfx/data_rx.c @@ -103,11 +103,9 @@ static int wfx_drop_encrypt_data(struct wfx_dev *wdev, void wfx_rx_cb(struct wfx_vif *wvif, const struct hif_ind_rx *arg, struct sk_buff *skb) { - int link_id = arg->rx_flags.peer_sta_id; struct ieee80211_rx_status *hdr = IEEE80211_SKB_RXCB(skb); struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; - struct wfx_link_entry *entry = NULL; memset(hdr, 0, sizeof(*hdr)); @@ -117,11 +115,6 @@ void wfx_rx_cb(struct wfx_vif *wvif, ieee80211_is_beacon(frame->frame_control))) goto drop; - if (link_id && link_id <= WFX_MAX_STA_IN_AP_MODE) { - entry = &wvif->link_id_db[link_id - 1]; - entry->timestamp = jiffies; - } - if (arg->status == HIF_STATUS_MICFAILURE) hdr->flag |= RX_FLAG_MMIC_ERROR; else if (arg->status) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index 9313c8f5d4d8..8c9f986ec672 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -17,7 +17,6 @@ #include "hif_tx_mib.h" #define WFX_INVALID_RATE_ID 15 -#define WFX_LINK_ID_NO_ASSOC 15 #define WFX_LINK_ID_GC_TIMEOUT ((unsigned long)(10 * HZ)) static int wfx_get_hw_rate(struct wfx_dev *wdev, @@ -265,156 +264,6 @@ void wfx_tx_policy_init(struct wfx_vif *wvif) list_add(&cache->cache[i].link, &cache->free); } -/* Link ID related functions */ - -static int wfx_alloc_link_id(struct wfx_vif *wvif, const u8 *mac) -{ - int i, ret = 0; - unsigned long oldest; - - spin_lock_bh(&wvif->ps_state_lock); - for (i = 0; i < WFX_MAX_STA_IN_AP_MODE; ++i) { - if (!wvif->link_id_db[i].status) { - ret = i + 1; - break; - } else if (wvif->link_id_db[i].status != WFX_LINK_HARD && - !wvif->wdev->tx_queue_stats.link_map_cache[i + 1]) { - if (!ret || time_after(oldest, wvif->link_id_db[i].timestamp)) { - oldest = wvif->link_id_db[i].timestamp; - ret = i + 1; - } - } - } - - if (ret) { - struct wfx_link_entry *entry = &wvif->link_id_db[ret - 1]; - - entry->status = WFX_LINK_RESERVE; - ether_addr_copy(entry->mac, mac); - wfx_tx_lock(wvif->wdev); - - if (!schedule_work(&wvif->link_id_work)) - wfx_tx_unlock(wvif->wdev); - } else { - dev_info(wvif->wdev->dev, "no more link-id available\n"); - } - spin_unlock_bh(&wvif->ps_state_lock); - return ret; -} - -int wfx_find_link_id(struct wfx_vif *wvif, const u8 *mac) -{ - int i, ret = 0; - - spin_lock_bh(&wvif->ps_state_lock); - for (i = 0; i < WFX_MAX_STA_IN_AP_MODE; ++i) { - if (ether_addr_equal(mac, wvif->link_id_db[i].mac) && - wvif->link_id_db[i].status) { - wvif->link_id_db[i].timestamp = jiffies; - ret = i + 1; - break; - } - } - spin_unlock_bh(&wvif->ps_state_lock); - return ret; -} - -static int wfx_map_link(struct wfx_vif *wvif, - struct wfx_link_entry *link_entry, int sta_id) -{ - int ret; - - ret = hif_map_link(wvif, link_entry->mac, 0, sta_id); - - if (ret == 0) - /* Save the MAC address currently associated with the peer - * for future unmap request - */ - ether_addr_copy(link_entry->old_mac, link_entry->mac); - - return ret; -} - -int wfx_unmap_link(struct wfx_vif *wvif, int sta_id) -{ - u8 *mac_addr = NULL; - - if (sta_id) - mac_addr = wvif->link_id_db[sta_id - 1].old_mac; - - return hif_map_link(wvif, mac_addr, 1, sta_id); -} - -void wfx_link_id_gc_work(struct work_struct *work) -{ - struct wfx_vif *wvif = - container_of(work, struct wfx_vif, link_id_gc_work.work); - unsigned long now = jiffies; - unsigned long next_gc = -1; - long ttl; - u32 mask; - int i; - - if (wvif->state != WFX_STATE_AP) - return; - - wfx_tx_lock_flush(wvif->wdev); - spin_lock_bh(&wvif->ps_state_lock); - for (i = 0; i < WFX_MAX_STA_IN_AP_MODE; ++i) { - bool need_reset = false; - - mask = BIT(i + 1); - if (wvif->link_id_db[i].status == WFX_LINK_RESERVE || - (wvif->link_id_db[i].status == WFX_LINK_HARD && - !(wvif->link_id_map & mask))) { - if (wvif->link_id_map & mask) { - wvif->sta_asleep_mask &= ~mask; - wvif->pspoll_mask &= ~mask; - need_reset = true; - } - wvif->link_id_map |= mask; - if (wvif->link_id_db[i].status != WFX_LINK_HARD) - wvif->link_id_db[i].status = WFX_LINK_SOFT; - - spin_unlock_bh(&wvif->ps_state_lock); - if (need_reset) - wfx_unmap_link(wvif, i + 1); - wfx_map_link(wvif, &wvif->link_id_db[i], i + 1); - next_gc = min(next_gc, WFX_LINK_ID_GC_TIMEOUT); - spin_lock_bh(&wvif->ps_state_lock); - } else if (wvif->link_id_db[i].status == WFX_LINK_SOFT) { - ttl = wvif->link_id_db[i].timestamp - now + - WFX_LINK_ID_GC_TIMEOUT; - if (ttl <= 0) { - need_reset = true; - wvif->link_id_db[i].status = WFX_LINK_OFF; - wvif->link_id_map &= ~mask; - wvif->sta_asleep_mask &= ~mask; - wvif->pspoll_mask &= ~mask; - spin_unlock_bh(&wvif->ps_state_lock); - wfx_unmap_link(wvif, i + 1); - spin_lock_bh(&wvif->ps_state_lock); - } else { - next_gc = min_t(unsigned long, next_gc, ttl); - } - } - } - spin_unlock_bh(&wvif->ps_state_lock); - if (next_gc != -1) - schedule_delayed_work(&wvif->link_id_gc_work, next_gc); - wfx_tx_unlock(wvif->wdev); -} - -void wfx_link_id_work(struct work_struct *work) -{ - struct wfx_vif *wvif = - container_of(work, struct wfx_vif, link_id_work); - - wfx_tx_flush(wvif->wdev); - wfx_link_id_gc_work(&wvif->link_id_gc_work.work); - wfx_tx_unlock(wvif->wdev); -} - /* Tx implementation */ static bool ieee80211_is_action_back(struct ieee80211_hdr *hdr) @@ -447,9 +296,6 @@ static void wfx_tx_manage_pm(struct wfx_vif *wvif, struct ieee80211_hdr *hdr, if (wvif->sta_asleep_mask) schedule_work(&wvif->mcast_start_work); } - - if (tx_priv->raw_link_id) - wvif->link_id_db[tx_priv->raw_link_id - 1].timestamp = jiffies; spin_unlock_bh(&wvif->ps_state_lock); if (sta && tx_priv->tid < WFX_MAX_TID) { @@ -468,7 +314,6 @@ static u8 wfx_tx_get_raw_link_id(struct wfx_vif *wvif, struct wfx_sta_priv *sta_priv = sta ? (struct wfx_sta_priv *) &sta->drv_priv : NULL; const u8 *da = ieee80211_get_DA(hdr); - int ret; if (sta_priv && sta_priv->link_id) return sta_priv->link_id; @@ -476,14 +321,7 @@ static u8 wfx_tx_get_raw_link_id(struct wfx_vif *wvif, return 0; if (is_multicast_ether_addr(da)) return 0; - ret = wfx_find_link_id(wvif, da); - if (!ret) - ret = wfx_alloc_link_id(wvif, da); - if (!ret) { - dev_err(wvif->wdev->dev, "no more link-id available\n"); - return WFX_LINK_ID_NO_ASSOC; - } - return ret; + return WFX_LINK_ID_NO_ASSOC; } static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates) diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h index d02a7b325b27..83720b343484 100644 --- a/drivers/staging/wfx/data_tx.h +++ b/drivers/staging/wfx/data_tx.h @@ -18,20 +18,6 @@ struct wfx_tx_priv; struct wfx_dev; struct wfx_vif; -enum wfx_link_status { - WFX_LINK_OFF, - WFX_LINK_RESERVE, - WFX_LINK_SOFT, - WFX_LINK_HARD, -}; - -struct wfx_link_entry { - unsigned long timestamp; - enum wfx_link_status status; - u8 mac[ETH_ALEN]; - u8 old_mac[ETH_ALEN]; -}; - struct tx_policy { struct list_head link; int usage_count; @@ -63,11 +49,6 @@ void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg); void wfx_skb_dtor(struct wfx_dev *wdev, struct sk_buff *skb); -int wfx_unmap_link(struct wfx_vif *wvif, int link_id); -void wfx_link_id_work(struct work_struct *work); -void wfx_link_id_gc_work(struct work_struct *work); -int wfx_find_link_id(struct wfx_vif *wvif, const u8 *mac); - static inline struct wfx_tx_priv *wfx_skb_tx_priv(struct sk_buff *skb) { struct ieee80211_tx_info *tx_info; diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index 92bb9a794f30..3d40388739e3 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -378,13 +378,8 @@ static bool hif_handle_tx_data(struct wfx_vif *wvif, struct sk_buff *skb, action = do_drop; break; case NL80211_IFTYPE_AP: - if (!wvif->state) { + if (!wvif->state) action = do_drop; - } else if (!(BIT(tx_priv->raw_link_id) & - (BIT(0) | wvif->link_id_map))) { - dev_warn(wvif->wdev->dev, "a frame with expired link-id is dropped\n"); - action = do_drop; - } break; case NL80211_IFTYPE_ADHOC: if (wvif->state != WFX_STATE_IBSS) diff --git a/drivers/staging/wfx/queue.h b/drivers/staging/wfx/queue.h index 21566e48b2c2..813c2d09e034 100644 --- a/drivers/staging/wfx/queue.h +++ b/drivers/staging/wfx/queue.h @@ -13,9 +13,10 @@ #include "hif_api_cmd.h" #define WFX_MAX_STA_IN_AP_MODE 14 -#define WFX_LINK_ID_AFTER_DTIM (WFX_MAX_STA_IN_AP_MODE + 1) -#define WFX_LINK_ID_UAPSD (WFX_MAX_STA_IN_AP_MODE + 2) -#define WFX_LINK_ID_MAX (WFX_MAX_STA_IN_AP_MODE + 3) +#define WFX_LINK_ID_NO_ASSOC 15 +#define WFX_LINK_ID_AFTER_DTIM (WFX_LINK_ID_NO_ASSOC + 1) +#define WFX_LINK_ID_UAPSD (WFX_LINK_ID_NO_ASSOC + 2) +#define WFX_LINK_ID_MAX (WFX_LINK_ID_NO_ASSOC + 3) struct wfx_dev; struct wfx_vif; diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index b7d21540d9a2..75c1e2aecc23 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -573,28 +573,26 @@ static void wfx_unjoin_work(struct work_struct *work) int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv; - struct wfx_link_entry *entry; spin_lock_init(&sta_priv->lock); - if (wvif->vif->type != NL80211_IFTYPE_AP) - return 0; - sta_priv->vif_id = wvif->id; - sta_priv->link_id = wfx_find_link_id(wvif, sta->addr); - if (!sta_priv->link_id) { - dev_warn(wdev->dev, "mo more link-id available\n"); - return -ENOENT; - } - entry = &wvif->link_id_db[sta_priv->link_id - 1]; + // FIXME: in station mode, the current API interprets new link-id as a + // tdls peer. + if (vif->type == NL80211_IFTYPE_STATION) + return 0; + sta_priv->link_id = ffz(wvif->link_id_map); + wvif->link_id_map |= BIT(sta_priv->link_id); + WARN_ON(!sta_priv->link_id); + WARN_ON(sta_priv->link_id >= WFX_MAX_STA_IN_AP_MODE); + hif_map_link(wvif, sta->addr, 0, sta_priv->link_id); + spin_lock_bh(&wvif->ps_state_lock); if ((sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) == IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) wvif->sta_asleep_mask |= BIT(sta_priv->link_id); - entry->status = WFX_LINK_HARD; spin_unlock_bh(&wvif->ps_state_lock); return 0; } @@ -602,23 +600,15 @@ int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv; - struct wfx_link_entry *entry; - if (wvif->vif->type != NL80211_IFTYPE_AP || !sta_priv->link_id) + // FIXME: see note in wfx_sta_add() + if (vif->type == NL80211_IFTYPE_STATION) return 0; - - entry = &wvif->link_id_db[sta_priv->link_id - 1]; - spin_lock_bh(&wvif->ps_state_lock); - entry->status = WFX_LINK_RESERVE; - entry->timestamp = jiffies; - wfx_tx_lock(wdev); - if (!schedule_work(&wvif->link_id_work)) - wfx_tx_unlock(wdev); - spin_unlock_bh(&wvif->ps_state_lock); - flush_work(&wvif->link_id_work); + // FIXME add a mutex? + hif_map_link(wvif, sta->addr, 1, sta_priv->link_id); + wvif->link_id_map &= ~BIT(sta_priv->link_id); return 0; } @@ -627,8 +617,6 @@ static int wfx_start_ap(struct wfx_vif *wvif) int ret; wvif->beacon_int = wvif->vif->bss_conf.beacon_int; - memset(&wvif->link_id_db, 0, sizeof(wvif->link_id_db)); - wvif->wdev->tx_burst_idx = -1; ret = hif_start(wvif, &wvif->vif->bss_conf, wvif->channel); if (ret) @@ -861,7 +849,7 @@ static void wfx_ps_notify(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd, dev_warn(wvif->wdev->dev, "unsupported notify command\n"); bit = 0; } else { - bit = wvif->link_id_map; + bit = wvif->link_id_map & ~1; } prev = wvif->sta_asleep_mask & bit; @@ -1114,9 +1102,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) wvif->vif = vif; wvif->wdev = wdev; - INIT_WORK(&wvif->link_id_work, wfx_link_id_work); - INIT_DELAYED_WORK(&wvif->link_id_gc_work, wfx_link_id_gc_work); - + wvif->link_id_map = 1; // link-id 0 is reserved for multicast spin_lock_init(&wvif->ps_state_lock); INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work); @@ -1171,11 +1157,11 @@ void wfx_remove_interface(struct ieee80211_hw *hw, { struct wfx_dev *wdev = hw->priv; struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; - int i; wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300)); mutex_lock(&wdev->conf_mutex); + WARN(wvif->link_id_map != 1, "corrupted state"); switch (wvif->state) { case WFX_STATE_PRE_STA: case WFX_STATE_STA: @@ -1185,13 +1171,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw, wfx_tx_unlock(wdev); break; case WFX_STATE_AP: - for (i = 0; wvif->link_id_map; ++i) { - if (wvif->link_id_map & BIT(i)) { - wfx_unmap_link(wvif, i); - wvif->link_id_map &= ~BIT(i); - } - } - memset(wvif->link_id_db, 0, sizeof(wvif->link_id_db)); wvif->sta_asleep_mask = 0; wvif->mcast_tx = false; wvif->aid0_bit_set = false; @@ -1213,7 +1192,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw, wfx_cqm_bssloss_sm(wvif, 0, 0, 0); cancel_work_sync(&wvif->unjoin_work); - cancel_delayed_work_sync(&wvif->link_id_gc_work); del_timer_sync(&wvif->mcast_timeout); wfx_free_event_queue(wvif); diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index cb359150e2ad..365aacc073fb 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -74,9 +74,6 @@ struct wfx_vif { struct delayed_work bss_loss_work; u32 link_id_map; - struct wfx_link_entry link_id_db[WFX_MAX_STA_IN_AP_MODE]; - struct delayed_work link_id_gc_work; - struct work_struct link_id_work; bool aid0_bit_set; bool mcast_tx; From 98511a91b126901e1392e1a6cf51ef94dc094f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:16 +0000 Subject: [PATCH 294/353] staging: wfx: check that no tx is pending before release sta MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just for sanity. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-52-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 75c1e2aecc23..33955278d9d3 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -602,7 +602,10 @@ int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv; + int i; + for (i = 0; i < WFX_MAX_TID; i++) + WARN(sta_priv->buffered[i], "release station while Tx is in progress"); // FIXME: see note in wfx_sta_add() if (vif->type == NL80211_IFTYPE_STATION) return 0; From df3519a328aafbde521e6011ebb254853a98cfa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:18 +0000 Subject: [PATCH 295/353] staging: wfx: replace wfx_tx_get_tid() with ieee80211_get_tid() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wfx_tx_get_tid() was used as a wrapper around ieee80211_get_tid(). It did sometime return WFX_MAX_TID to ask to upper layers to not include the frame in "buffered" counter. The objective of this behavior is not clear, but tests has shown that wfx_tx_get_tid() can be replaced by ieee80211_get_tid() without any regressions. BTW, it is not necessary to save the tid in tx_rpiv since it can be retrieved from the 802.11 header. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-53-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 23 ++++++----------------- drivers/staging/wfx/data_tx.h | 1 - drivers/staging/wfx/sta.c | 2 +- drivers/staging/wfx/sta.h | 5 +---- 4 files changed, 8 insertions(+), 23 deletions(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index 8c9f986ec672..7da1afd6e9b5 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -283,6 +283,7 @@ static void wfx_tx_manage_pm(struct wfx_vif *wvif, struct ieee80211_hdr *hdr, { u32 mask = ~BIT(tx_priv->raw_link_id); struct wfx_sta_priv *sta_priv; + int tid = ieee80211_get_tid(hdr); spin_lock_bh(&wvif->ps_state_lock); if (ieee80211_is_auth(hdr->frame_control)) { @@ -298,11 +299,11 @@ static void wfx_tx_manage_pm(struct wfx_vif *wvif, struct ieee80211_hdr *hdr, } spin_unlock_bh(&wvif->ps_state_lock); - if (sta && tx_priv->tid < WFX_MAX_TID) { + if (sta) { sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; spin_lock_bh(&sta_priv->lock); - sta_priv->buffered[tx_priv->tid]++; - ieee80211_sta_set_buffered(sta, tx_priv->tid, true); + sta_priv->buffered[tid]++; + ieee80211_sta_set_buffered(sta, tid, true); spin_unlock_bh(&sta_priv->lock); } } @@ -418,17 +419,6 @@ static struct hif_ht_tx_parameters wfx_tx_get_tx_parms(struct wfx_dev *wdev, str return ret; } -static u8 wfx_tx_get_tid(struct ieee80211_hdr *hdr) -{ - // FIXME: ieee80211_get_tid(hdr) should be sufficient for all cases. - if (!ieee80211_is_data(hdr->frame_control)) - return WFX_MAX_TID; - if (ieee80211_is_data_qos(hdr->frame_control)) - return ieee80211_get_tid(hdr); - else - return 0; -} - static int wfx_tx_get_icv_len(struct ieee80211_key_conf *hw_key) { int mic_space; @@ -460,7 +450,6 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, memset(tx_info->rate_driver_data, 0, sizeof(struct wfx_tx_priv)); // Fill tx_priv tx_priv = (struct wfx_tx_priv *)tx_info->rate_driver_data; - tx_priv->tid = wfx_tx_get_tid(hdr); tx_priv->raw_link_id = wfx_tx_get_raw_link_id(wvif, sta, hdr); tx_priv->link_id = tx_priv->raw_link_id; if (ieee80211_has_protected(hdr->frame_control)) @@ -634,11 +623,11 @@ static void wfx_notify_buffered_tx(struct wfx_vif *wvif, struct sk_buff *skb) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_sta *sta; struct wfx_sta_priv *sta_priv; - int tid = wfx_tx_get_tid(hdr); + int tid = ieee80211_get_tid(hdr); rcu_read_lock(); // protect sta sta = ieee80211_find_sta(wvif->vif, hdr->addr1); - if (sta && tid < WFX_MAX_TID) { + if (sta) { sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; spin_lock_bh(&sta_priv->lock); WARN(!sta_priv->buffered[tid], "inconsistent notification"); diff --git a/drivers/staging/wfx/data_tx.h b/drivers/staging/wfx/data_tx.h index 83720b343484..04b2147101b6 100644 --- a/drivers/staging/wfx/data_tx.h +++ b/drivers/staging/wfx/data_tx.h @@ -38,7 +38,6 @@ struct wfx_tx_priv { struct ieee80211_key_conf *hw_key; u8 link_id; u8 raw_link_id; - u8 tid; } __packed; void wfx_tx_policy_init(struct wfx_vif *wvif); diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 33955278d9d3..aa1a68b61ac5 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -604,7 +604,7 @@ int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv; int i; - for (i = 0; i < WFX_MAX_TID; i++) + for (i = 0; i < ARRAY_SIZE(sta_priv->buffered); i++) WARN(sta_priv->buffered[i], "release station while Tx is in progress"); // FIXME: see note in wfx_sta_add() if (vif->type == NL80211_IFTYPE_STATION) diff --git a/drivers/staging/wfx/sta.h b/drivers/staging/wfx/sta.h index 47d94d6b8590..e832405d604e 100644 --- a/drivers/staging/wfx/sta.h +++ b/drivers/staging/wfx/sta.h @@ -12,9 +12,6 @@ #include "hif_api_cmd.h" -// FIXME: use IEEE80211_NUM_TIDS -#define WFX_MAX_TID 8 - struct wfx_dev; struct wfx_vif; @@ -40,7 +37,7 @@ struct wfx_grp_addr_table { struct wfx_sta_priv { int link_id; int vif_id; - u8 buffered[WFX_MAX_TID]; + u8 buffered[IEEE80211_NUM_TIDS]; // Ensure atomicity of "buffered" and calls to ieee80211_sta_set_buffered() spinlock_t lock; }; From 2e57865e79cfe82afcefff553300bb0eea07c1c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:19 +0000 Subject: [PATCH 296/353] staging: wfx: pspoll_mask make no sense MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pspoll_mask is here to send data buffered in driver. But since station is marked buffered, TIM for this station is 1 and mac80211 will call sta_notify when a ps-poll is received. So pspoll_mask is useless and sta_alseep_mask is sufficient. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-54-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_rx.c | 39 ----------------------------------- drivers/staging/wfx/data_tx.c | 4 +--- drivers/staging/wfx/queue.c | 8 ++----- drivers/staging/wfx/sta.c | 2 -- drivers/staging/wfx/wfx.h | 1 - 5 files changed, 3 insertions(+), 51 deletions(-) diff --git a/drivers/staging/wfx/data_rx.c b/drivers/staging/wfx/data_rx.c index 699e2d60fa89..5d198457c6ce 100644 --- a/drivers/staging/wfx/data_rx.c +++ b/drivers/staging/wfx/data_rx.c @@ -13,41 +13,6 @@ #include "bh.h" #include "sta.h" -static int wfx_handle_pspoll(struct wfx_vif *wvif, struct sk_buff *skb) -{ - struct ieee80211_sta *sta; - struct ieee80211_pspoll *pspoll = (struct ieee80211_pspoll *)skb->data; - int link_id = 0; - u32 pspoll_mask = 0; - int i; - - if (wvif->state != WFX_STATE_AP) - return 1; - if (!ether_addr_equal(wvif->vif->addr, pspoll->bssid)) - return 1; - - rcu_read_lock(); - sta = ieee80211_find_sta(wvif->vif, pspoll->ta); - if (sta) - link_id = ((struct wfx_sta_priv *)&sta->drv_priv)->link_id; - rcu_read_unlock(); - if (link_id) - pspoll_mask = BIT(link_id); - else - return 1; - - wvif->pspoll_mask |= pspoll_mask; - /* Do not report pspols if data for given link id is queued already. */ - for (i = 0; i < IEEE80211_NUM_ACS; ++i) { - if (wfx_tx_queue_get_num_queued(&wvif->wdev->tx_queue[i], - pspoll_mask)) { - wfx_bh_request_tx(wvif->wdev); - return 1; - } - } - return 0; -} - static int wfx_drop_encrypt_data(struct wfx_dev *wdev, const struct hif_ind_rx *arg, struct sk_buff *skb) @@ -125,10 +90,6 @@ void wfx_rx_cb(struct wfx_vif *wvif, goto drop; } - if (ieee80211_is_pspoll(frame->frame_control)) - if (wfx_handle_pspoll(wvif, skb)) - goto drop; - hdr->band = NL80211_BAND_2GHZ; hdr->freq = ieee80211_channel_to_frequency(arg->channel_number, hdr->band); diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index 7da1afd6e9b5..7914c06578aa 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -286,10 +286,8 @@ static void wfx_tx_manage_pm(struct wfx_vif *wvif, struct ieee80211_hdr *hdr, int tid = ieee80211_get_tid(hdr); spin_lock_bh(&wvif->ps_state_lock); - if (ieee80211_is_auth(hdr->frame_control)) { + if (ieee80211_is_auth(hdr->frame_control)) wvif->sta_asleep_mask &= mask; - wvif->pspoll_mask &= mask; - } if (tx_priv->link_id == WFX_LINK_ID_AFTER_DTIM && !wvif->mcast_buffered) { diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index 3d40388739e3..42d64534c92c 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -493,12 +493,10 @@ static int wfx_tx_queue_mask_get(struct wfx_vif *wvif, /* Search for unicast traffic */ tx_allowed_mask = ~wvif->sta_asleep_mask; tx_allowed_mask |= BIT(WFX_LINK_ID_UAPSD); - if (wvif->sta_asleep_mask) { - tx_allowed_mask |= wvif->pspoll_mask; + if (wvif->sta_asleep_mask) tx_allowed_mask &= ~BIT(WFX_LINK_ID_AFTER_DTIM); - } else { + else tx_allowed_mask |= BIT(WFX_LINK_ID_AFTER_DTIM); - } idx = wfx_get_prio_queue(wvif, tx_allowed_mask, &total); if (idx < 0) return -ENOENT; @@ -585,8 +583,6 @@ struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev) if (hif_handle_tx_data(wvif, skb, queue)) continue; /* Handled by WSM */ - wvif->pspoll_mask &= ~BIT(tx_priv->raw_link_id); - /* allow bursting if txop is set */ if (wvif->edca_params[queue_num].txop) burst = (int)wfx_tx_queue_get_num_queued(queue, tx_allowed_mask) + 1; diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index aa1a68b61ac5..c249a2953bb0 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -867,7 +867,6 @@ static void wfx_ps_notify(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd, case STA_NOTIFY_AWAKE: if (prev) { wvif->sta_asleep_mask &= ~bit; - wvif->pspoll_mask &= ~bit; if (link_id && !wvif->sta_asleep_mask) schedule_work(&wvif->mcast_stop_work); wfx_bh_request_tx(wvif->wdev); @@ -1178,7 +1177,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw, wvif->mcast_tx = false; wvif->aid0_bit_set = false; wvif->mcast_buffered = false; - wvif->pspoll_mask = 0; /* reset.link_id = 0; */ hif_reset(wvif, false); break; diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 365aacc073fb..8491f050478d 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -91,7 +91,6 @@ struct wfx_vif { struct work_struct tx_policy_upload_work; u32 sta_asleep_mask; - u32 pspoll_mask; spinlock_t ps_state_lock; struct work_struct update_tim_work; From 6537adc3e3076e9dc522d827ec412812f633ec7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:21 +0000 Subject: [PATCH 297/353] staging: wfx: sta and dtim MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wfx_ps_notify() is called for any changes in the TIM. However, association ID 0 is a very special case that should be handled independently. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-55-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index c249a2953bb0..9f4c566517a1 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -839,21 +839,13 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, wfx_do_join(wvif); } -static void wfx_ps_notify(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd, - int link_id) +static void wfx_ps_notify_sta(struct wfx_vif *wvif, + enum sta_notify_cmd notify_cmd, int link_id) { u32 bit, prev; spin_lock_bh(&wvif->ps_state_lock); - /* Zero link id means "for all link IDs" */ - if (link_id) { - bit = BIT(link_id); - } else if (notify_cmd != STA_NOTIFY_AWAKE) { - dev_warn(wvif->wdev->dev, "unsupported notify command\n"); - bit = 0; - } else { - bit = wvif->link_id_map & ~1; - } + bit = BIT(link_id); prev = wvif->sta_asleep_mask & bit; switch (notify_cmd) { @@ -867,7 +859,7 @@ static void wfx_ps_notify(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd, case STA_NOTIFY_AWAKE: if (prev) { wvif->sta_asleep_mask &= ~bit; - if (link_id && !wvif->sta_asleep_mask) + if (!wvif->sta_asleep_mask) schedule_work(&wvif->mcast_stop_work); wfx_bh_request_tx(wvif->wdev); } @@ -882,7 +874,7 @@ void wfx_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv; struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv; - wfx_ps_notify(wvif, notify_cmd, sta_priv->link_id); + wfx_ps_notify_sta(wvif, notify_cmd, sta_priv->link_id); } static int wfx_update_tim(struct wfx_vif *wvif) @@ -993,6 +985,14 @@ int wfx_ampdu_action(struct ieee80211_hw *hw, return -ENOTSUPP; } +static void wfx_dtim_notify(struct wfx_vif *wvif) +{ + spin_lock_bh(&wvif->ps_state_lock); + wvif->sta_asleep_mask = 0; + wfx_bh_request_tx(wvif->wdev); + spin_unlock_bh(&wvif->ps_state_lock); +} + void wfx_suspend_resume(struct wfx_vif *wvif, const struct hif_ind_suspend_resume_tx *arg) { @@ -1013,12 +1013,9 @@ void wfx_suspend_resume(struct wfx_vif *wvif, if (cancel_tmo) del_timer_sync(&wvif->mcast_timeout); } else if (arg->suspend_resume_flags.resume) { - // FIXME: should change each station status independently - wfx_ps_notify(wvif, STA_NOTIFY_AWAKE, 0); - wfx_bh_request_tx(wvif->wdev); + wfx_dtim_notify(wvif); } else { - // FIXME: should change each station status independently - wfx_ps_notify(wvif, STA_NOTIFY_SLEEP, 0); + dev_warn(wvif->wdev->dev, "unsupported suspend/resume notification\n"); } } From b5d4d98ec807a248e41ed7e8a3a649b8d88a745c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:22 +0000 Subject: [PATCH 298/353] staging: wfx: firmware never return PS status for stations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At the beginning, firmware could send suspend_resume indication to notify that a station wake up or sleep down. However, mac80211 already handles power save status of stations and this behavior has been removed from the firmware. So now, when suspend_resume indication is received, it is always to notify that a DTIM is about to be sent. So, it is possible to simply wfx_suspend_resume(). Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-56-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 43 ++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 9f4c566517a1..7c9e93f52993 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -985,38 +985,29 @@ int wfx_ampdu_action(struct ieee80211_hw *hw, return -ENOTSUPP; } -static void wfx_dtim_notify(struct wfx_vif *wvif) -{ - spin_lock_bh(&wvif->ps_state_lock); - wvif->sta_asleep_mask = 0; - wfx_bh_request_tx(wvif->wdev); - spin_unlock_bh(&wvif->ps_state_lock); -} - void wfx_suspend_resume(struct wfx_vif *wvif, const struct hif_ind_suspend_resume_tx *arg) { - if (arg->suspend_resume_flags.bc_mc_only) { - bool cancel_tmo = false; + bool cancel_tmo = false; - spin_lock_bh(&wvif->ps_state_lock); - if (!arg->suspend_resume_flags.resume) - wvif->mcast_tx = false; - else - wvif->mcast_tx = wvif->aid0_bit_set && - wvif->mcast_buffered; - if (wvif->mcast_tx) { - cancel_tmo = true; - wfx_bh_request_tx(wvif->wdev); - } - spin_unlock_bh(&wvif->ps_state_lock); - if (cancel_tmo) - del_timer_sync(&wvif->mcast_timeout); - } else if (arg->suspend_resume_flags.resume) { - wfx_dtim_notify(wvif); - } else { + if (!arg->suspend_resume_flags.bc_mc_only) { dev_warn(wvif->wdev->dev, "unsupported suspend/resume notification\n"); + return; } + + spin_lock_bh(&wvif->ps_state_lock); + if (!arg->suspend_resume_flags.resume) + wvif->mcast_tx = false; + else + wvif->mcast_tx = wvif->aid0_bit_set && + wvif->mcast_buffered; + if (wvif->mcast_tx) { + cancel_tmo = true; + wfx_bh_request_tx(wvif->wdev); + } + spin_unlock_bh(&wvif->ps_state_lock); + if (cancel_tmo) + del_timer_sync(&wvif->mcast_timeout); } int wfx_add_chanctx(struct ieee80211_hw *hw, From 22c03264e5a914966c93baa367d63eb77f60ebaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:24 +0000 Subject: [PATCH 299/353] staging: wfx: simplify wfx_suspend_resume_mc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Indeed, it is not necessary to pass whole hif_ind_suspend_resume_tx to wfx_suspend_resume_mc(). In add, the structure hif_ind_suspend_resume_tx come from hardware API. It is not intended to be manipulated in upper layers of the driver. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-57-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 7 +------ drivers/staging/wfx/hif_rx.c | 6 +++++- drivers/staging/wfx/sta.c | 10 ++-------- drivers/staging/wfx/sta.h | 3 +-- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index 7914c06578aa..8710383f66e5 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -600,13 +600,8 @@ void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg) tx_info->flags |= IEEE80211_TX_STAT_ACK; } else if (arg->status == HIF_REQUEUE) { /* "REQUEUE" means "implicit suspend" */ - struct hif_ind_suspend_resume_tx suspend = { - .suspend_resume_flags.resume = 0, - .suspend_resume_flags.bc_mc_only = 1, - }; - WARN(!arg->tx_result_flags.requeue, "incoherent status and result_flags"); - wfx_suspend_resume(wvif, &suspend); + wfx_suspend_resume_mc(wvif, STA_NOTIFY_SLEEP); tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; } else { if (wvif->bss_loss_state && diff --git a/drivers/staging/wfx/hif_rx.c b/drivers/staging/wfx/hif_rx.c index f04afc6db9a5..f798cd6973b6 100644 --- a/drivers/staging/wfx/hif_rx.c +++ b/drivers/staging/wfx/hif_rx.c @@ -230,7 +230,11 @@ static int hif_suspend_resume_indication(struct wfx_dev *wdev, const struct hif_ind_suspend_resume_tx *body = buf; WARN_ON(!wvif); - wfx_suspend_resume(wvif, body); + WARN(!body->suspend_resume_flags.bc_mc_only, "unsupported suspend/resume notification"); + if (body->suspend_resume_flags.resume) + wfx_suspend_resume_mc(wvif, STA_NOTIFY_AWAKE); + else + wfx_suspend_resume_mc(wvif, STA_NOTIFY_SLEEP); return 0; } diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index 7c9e93f52993..bdc15554958c 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -985,18 +985,12 @@ int wfx_ampdu_action(struct ieee80211_hw *hw, return -ENOTSUPP; } -void wfx_suspend_resume(struct wfx_vif *wvif, - const struct hif_ind_suspend_resume_tx *arg) +void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd) { bool cancel_tmo = false; - if (!arg->suspend_resume_flags.bc_mc_only) { - dev_warn(wvif->wdev->dev, "unsupported suspend/resume notification\n"); - return; - } - spin_lock_bh(&wvif->ps_state_lock); - if (!arg->suspend_resume_flags.resume) + if (notify_cmd == STA_NOTIFY_SLEEP) wvif->mcast_tx = false; else wvif->mcast_tx = wvif->aid0_bit_set && diff --git a/drivers/staging/wfx/sta.h b/drivers/staging/wfx/sta.h index e832405d604e..cf99a8a74a81 100644 --- a/drivers/staging/wfx/sta.h +++ b/drivers/staging/wfx/sta.h @@ -82,8 +82,7 @@ void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf); // WSM Callbacks -void wfx_suspend_resume(struct wfx_vif *wvif, - const struct hif_ind_suspend_resume_tx *arg); +void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd cmd); // Other Helpers void wfx_cqm_bssloss_sm(struct wfx_vif *wvif, int init, int good, int bad); From a3c529a835890b0eecd324d9f0c37c67345f84e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:25 +0000 Subject: [PATCH 300/353] staging: wfx: simplify handling of IEEE80211_TX_CTL_SEND_AFTER_DTIM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When mac80211 ask for a frame to be sent after a DTIM, driver should: 1. Update TIM with multicast bit set (using update_ie). This function can be called whenever. 2. Keep buffered all frames marked "after dtim" 3. When it receive a suspend_resume indication (see wfx_suspend_resume_mc()), send all the buffered frames. This indication is sent by the firmware 4ms before the dtim. 4. If one of the frames returns status "REQUEUE", it means that the DTIM period was ended before to be able to send the frame. 5. When all the buffered frames were sent or if DTIM period was ended, driver should update the TIM with multicast bit reset. All the mess with the asynchronous works can be dropped. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-58-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 17 +++--- drivers/staging/wfx/hif_api_cmd.h | 3 +- drivers/staging/wfx/queue.c | 98 +++++++++++++++---------------- drivers/staging/wfx/queue.h | 1 + drivers/staging/wfx/sta.c | 78 ++---------------------- drivers/staging/wfx/wfx.h | 7 +-- 6 files changed, 66 insertions(+), 138 deletions(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index 8710383f66e5..c32994553633 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -288,13 +288,6 @@ static void wfx_tx_manage_pm(struct wfx_vif *wvif, struct ieee80211_hdr *hdr, spin_lock_bh(&wvif->ps_state_lock); if (ieee80211_is_auth(hdr->frame_control)) wvif->sta_asleep_mask &= mask; - - if (tx_priv->link_id == WFX_LINK_ID_AFTER_DTIM && - !wvif->mcast_buffered) { - wvif->mcast_buffered = true; - if (wvif->sta_asleep_mask) - schedule_work(&wvif->mcast_start_work); - } spin_unlock_bh(&wvif->ps_state_lock); if (sta) { @@ -479,6 +472,8 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, req->packet_id = queue_id << 16 | IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); req->data_flags.fc_offset = offset; + if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) + req->data_flags.after_dtim = 1; req->queue_id.peer_sta_id = tx_priv->raw_link_id; // Queue index are inverted between firmware and Linux req->queue_id.queue_id = 3 - queue_id; @@ -488,6 +483,8 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, // Auxiliary operations wfx_tx_manage_pm(wvif, hdr, tx_priv, sta); wfx_tx_queue_put(wvif->wdev, &wvif->wdev->tx_queue[queue_id], skb); + if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) + schedule_work(&wvif->update_tim_work); wfx_bh_request_tx(wvif->wdev); return 0; } @@ -599,9 +596,11 @@ void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg) else tx_info->flags |= IEEE80211_TX_STAT_ACK; } else if (arg->status == HIF_REQUEUE) { - /* "REQUEUE" means "implicit suspend" */ WARN(!arg->tx_result_flags.requeue, "incoherent status and result_flags"); - wfx_suspend_resume_mc(wvif, STA_NOTIFY_SLEEP); + if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { + wvif->after_dtim_tx_allowed = false; // DTIM period elapsed + schedule_work(&wvif->update_tim_work); + } tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; } else { if (wvif->bss_loss_state && diff --git a/drivers/staging/wfx/hif_api_cmd.h b/drivers/staging/wfx/hif_api_cmd.h index fc078d54bfbf..5554d6eddbf3 100644 --- a/drivers/staging/wfx/hif_api_cmd.h +++ b/drivers/staging/wfx/hif_api_cmd.h @@ -253,7 +253,8 @@ struct hif_queue { struct hif_data_flags { u8 more:1; u8 fc_offset:3; - u8 reserved:4; + u8 after_dtim:1; + u8 reserved:3; } __packed; struct hif_tx_flags { diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index 42d64534c92c..ec11a63a2ff9 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -235,7 +235,6 @@ static struct sk_buff *wfx_tx_queue_get(struct wfx_dev *wdev, break; } } - WARN_ON(!skb); if (skb) { tx_priv = wfx_skb_tx_priv(skb); tx_priv->xmit_timestamp = ktime_get(); @@ -473,23 +472,12 @@ static int wfx_get_prio_queue(struct wfx_vif *wvif, static int wfx_tx_queue_mask_get(struct wfx_vif *wvif, struct wfx_queue **queue_p, - u32 *tx_allowed_mask_p, - bool *more) + u32 *tx_allowed_mask_p) { int idx; u32 tx_allowed_mask; int total = 0; - /* Search for a queue with multicast frames buffered */ - if (wvif->mcast_tx) { - tx_allowed_mask = BIT(WFX_LINK_ID_AFTER_DTIM); - idx = wfx_get_prio_queue(wvif, tx_allowed_mask, &total); - if (idx >= 0) { - *more = total > 1; - goto found; - } - } - /* Search for unicast traffic */ tx_allowed_mask = ~wvif->sta_asleep_mask; tx_allowed_mask |= BIT(WFX_LINK_ID_UAPSD); @@ -501,64 +489,83 @@ static int wfx_tx_queue_mask_get(struct wfx_vif *wvif, if (idx < 0) return -ENOENT; -found: *queue_p = &wvif->wdev->tx_queue[idx]; *tx_allowed_mask_p = tx_allowed_mask; return 0; } +struct hif_msg *wfx_tx_queues_get_after_dtim(struct wfx_vif *wvif) +{ + struct wfx_dev *wdev = wvif->wdev; + struct ieee80211_tx_info *tx_info; + struct hif_msg *hif; + struct sk_buff *skb; + int i; + + for (i = 0; i < IEEE80211_NUM_ACS; ++i) { + skb_queue_walk(&wdev->tx_queue[i].queue, skb) { + tx_info = IEEE80211_SKB_CB(skb); + hif = (struct hif_msg *)skb->data; + if ((tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) && + (hif->interface == wvif->id)) + return (struct hif_msg *)skb->data; + } + } + return NULL; +} + struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev) { struct sk_buff *skb; struct hif_msg *hif = NULL; - struct hif_req_tx *req = NULL; struct wfx_queue *queue = NULL; struct wfx_queue *vif_queue = NULL; u32 tx_allowed_mask = 0; u32 vif_tx_allowed_mask = 0; const struct wfx_tx_priv *tx_priv = NULL; struct wfx_vif *wvif; - /* More is used only for broadcasts. */ - bool more = false; - bool vif_more = false; int not_found; int burst; + int i; + + if (atomic_read(&wdev->tx_lock)) + return NULL; + + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { + if (wvif->after_dtim_tx_allowed) { + for (i = 0; i < IEEE80211_NUM_ACS; ++i) { + skb = wfx_tx_queue_get(wvif->wdev, + &wdev->tx_queue[i], + BIT(WFX_LINK_ID_AFTER_DTIM)); + if (skb) { + hif = (struct hif_msg *)skb->data; + // Cannot happen since only one vif can + // be AP at time + WARN_ON(wvif->id != hif->interface); + return hif; + } + } + // No more multicast to sent + wvif->after_dtim_tx_allowed = false; + schedule_work(&wvif->update_tim_work); + } + } for (;;) { int ret = -ENOENT; int queue_num; - struct ieee80211_hdr *hdr; - - if (atomic_read(&wdev->tx_lock)) - return NULL; wvif = NULL; while ((wvif = wvif_iterate(wdev, wvif)) != NULL) { spin_lock_bh(&wvif->ps_state_lock); not_found = wfx_tx_queue_mask_get(wvif, &vif_queue, - &vif_tx_allowed_mask, - &vif_more); - - if (wvif->mcast_buffered && (not_found || !vif_more) && - (wvif->mcast_tx || - !wvif->sta_asleep_mask)) { - wvif->mcast_buffered = false; - if (wvif->mcast_tx) { - wvif->mcast_tx = false; - schedule_work(&wvif->mcast_stop_work); - } - } + &vif_tx_allowed_mask); spin_unlock_bh(&wvif->ps_state_lock); - if (vif_more) { - more = true; - tx_allowed_mask = vif_tx_allowed_mask; - queue = vif_queue; - ret = 0; - break; - } else if (!not_found) { + if (!not_found) { if (queue && queue != vif_queue) dev_info(wdev->dev, "vifs disagree about queue priority\n"); tx_allowed_mask |= vif_tx_allowed_mask; @@ -595,15 +602,6 @@ struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev) else wdev->tx_burst_idx = -1; - /* more buffered multicast/broadcast frames - * ==> set MoreData flag in IEEE 802.11 header - * to inform PS STAs - */ - if (more) { - req = (struct hif_req_tx *) hif->body; - hdr = (struct ieee80211_hdr *) (req->frame + req->data_flags.fc_offset); - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); - } return hif; } } diff --git a/drivers/staging/wfx/queue.h b/drivers/staging/wfx/queue.h index 813c2d09e034..096ae86135cc 100644 --- a/drivers/staging/wfx/queue.h +++ b/drivers/staging/wfx/queue.h @@ -47,6 +47,7 @@ void wfx_tx_queues_clear(struct wfx_dev *wdev); bool wfx_tx_queues_is_empty(struct wfx_dev *wdev); void wfx_tx_queues_wait_empty_vif(struct wfx_vif *wvif); struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev); +struct hif_msg *wfx_tx_queues_get_after_dtim(struct wfx_vif *wvif); void wfx_tx_queue_put(struct wfx_dev *wdev, struct wfx_queue *queue, struct sk_buff *skb); diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index bdc15554958c..a9b58e4a9fa3 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -851,16 +851,12 @@ static void wfx_ps_notify_sta(struct wfx_vif *wvif, switch (notify_cmd) { case STA_NOTIFY_SLEEP: if (!prev) { - if (wvif->mcast_buffered && !wvif->sta_asleep_mask) - schedule_work(&wvif->mcast_start_work); wvif->sta_asleep_mask |= bit; } break; case STA_NOTIFY_AWAKE: if (prev) { wvif->sta_asleep_mask &= ~bit; - if (!wvif->sta_asleep_mask) - schedule_work(&wvif->mcast_stop_work); wfx_bh_request_tx(wvif->wdev); } break; @@ -898,7 +894,7 @@ static int wfx_update_tim(struct wfx_vif *wvif) tim_ptr[2] = 0; /* Set/reset aid0 bit */ - if (wvif->aid0_bit_set) + if (wfx_tx_queues_get_after_dtim(wvif)) tim_ptr[4] |= 1; else tim_ptr[4] &= ~1; @@ -927,47 +923,12 @@ int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) return 0; } -static void wfx_mcast_start_work(struct work_struct *work) +void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd) { - struct wfx_vif *wvif = - container_of(work, struct wfx_vif, mcast_start_work); - struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf; - long tmo = conf->dtim_period * TU_TO_JIFFIES(wvif->beacon_int + 20); - - cancel_work_sync(&wvif->mcast_stop_work); - if (!wvif->aid0_bit_set) { - wfx_tx_lock_flush(wvif->wdev); - wvif->aid0_bit_set = true; - wfx_update_tim(wvif); - mod_timer(&wvif->mcast_timeout, jiffies + tmo); - wfx_tx_unlock(wvif->wdev); - } -} - -static void wfx_mcast_stop_work(struct work_struct *work) -{ - struct wfx_vif *wvif = container_of(work, struct wfx_vif, - mcast_stop_work); - - if (wvif->aid0_bit_set) { - del_timer_sync(&wvif->mcast_timeout); - wfx_tx_lock_flush(wvif->wdev); - wvif->aid0_bit_set = false; - wfx_update_tim(wvif); - wfx_tx_unlock(wvif->wdev); - } -} - -static void wfx_mcast_timeout(struct timer_list *t) -{ - struct wfx_vif *wvif = from_timer(wvif, t, mcast_timeout); - - dev_warn(wvif->wdev->dev, "multicast delivery timeout\n"); - spin_lock_bh(&wvif->ps_state_lock); - wvif->mcast_tx = wvif->aid0_bit_set && wvif->mcast_buffered; - if (wvif->mcast_tx) - wfx_bh_request_tx(wvif->wdev); - spin_unlock_bh(&wvif->ps_state_lock); + WARN(!wfx_tx_queues_get_after_dtim(wvif), "incorrect sequence"); + WARN(wvif->after_dtim_tx_allowed, "incorrect sequence"); + wvif->after_dtim_tx_allowed = true; + wfx_bh_request_tx(wvif->wdev); } int wfx_ampdu_action(struct ieee80211_hw *hw, @@ -985,25 +946,6 @@ int wfx_ampdu_action(struct ieee80211_hw *hw, return -ENOTSUPP; } -void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd) -{ - bool cancel_tmo = false; - - spin_lock_bh(&wvif->ps_state_lock); - if (notify_cmd == STA_NOTIFY_SLEEP) - wvif->mcast_tx = false; - else - wvif->mcast_tx = wvif->aid0_bit_set && - wvif->mcast_buffered; - if (wvif->mcast_tx) { - cancel_tmo = true; - wfx_bh_request_tx(wvif->wdev); - } - spin_unlock_bh(&wvif->ps_state_lock); - if (cancel_tmo) - del_timer_sync(&wvif->mcast_timeout); -} - int wfx_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf) { @@ -1090,10 +1032,6 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) spin_lock_init(&wvif->ps_state_lock); INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work); - INIT_WORK(&wvif->mcast_start_work, wfx_mcast_start_work); - INIT_WORK(&wvif->mcast_stop_work, wfx_mcast_stop_work); - timer_setup(&wvif->mcast_timeout, wfx_mcast_timeout, 0); - memset(&wvif->bss_params, 0, sizeof(wvif->bss_params)); mutex_init(&wvif->bss_loss_lock); @@ -1156,9 +1094,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw, break; case WFX_STATE_AP: wvif->sta_asleep_mask = 0; - wvif->mcast_tx = false; - wvif->aid0_bit_set = false; - wvif->mcast_buffered = false; /* reset.link_id = 0; */ hif_reset(wvif, false); break; @@ -1175,7 +1110,6 @@ void wfx_remove_interface(struct ieee80211_hw *hw, wfx_cqm_bssloss_sm(wvif, 0, 0, 0); cancel_work_sync(&wvif->unjoin_work); - del_timer_sync(&wvif->mcast_timeout); wfx_free_event_queue(wvif); wdev->vif[wvif->id] = NULL; diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 8491f050478d..5d61946e33e0 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -75,13 +75,8 @@ struct wfx_vif { u32 link_id_map; - bool aid0_bit_set; - bool mcast_tx; - bool mcast_buffered; + bool after_dtim_tx_allowed; struct wfx_grp_addr_table mcast_filter; - struct timer_list mcast_timeout; - struct work_struct mcast_start_work; - struct work_struct mcast_stop_work; s8 wep_default_key_id; struct sk_buff *wep_pending_skb; From ded6ca11af6bb0394a3c684b4c2e39c928ca4738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:27 +0000 Subject: [PATCH 301/353] staging: wfx: simplify wfx_ps_notify_sta() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wfx_ps_notify_sta() is too complex compared to the task it do. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-59-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/sta.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/staging/wfx/sta.c b/drivers/staging/wfx/sta.c index a9b58e4a9fa3..03d0f224ffdb 100644 --- a/drivers/staging/wfx/sta.c +++ b/drivers/staging/wfx/sta.c @@ -842,26 +842,14 @@ void wfx_bss_info_changed(struct ieee80211_hw *hw, static void wfx_ps_notify_sta(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd, int link_id) { - u32 bit, prev; - spin_lock_bh(&wvif->ps_state_lock); - bit = BIT(link_id); - prev = wvif->sta_asleep_mask & bit; - - switch (notify_cmd) { - case STA_NOTIFY_SLEEP: - if (!prev) { - wvif->sta_asleep_mask |= bit; - } - break; - case STA_NOTIFY_AWAKE: - if (prev) { - wvif->sta_asleep_mask &= ~bit; - wfx_bh_request_tx(wvif->wdev); - } - break; - } + if (notify_cmd == STA_NOTIFY_SLEEP) + wvif->sta_asleep_mask |= BIT(link_id); + else // notify_cmd == STA_NOTIFY_AWAKE + wvif->sta_asleep_mask &= ~BIT(link_id); spin_unlock_bh(&wvif->ps_state_lock); + if (notify_cmd == STA_NOTIFY_AWAKE) + wfx_bh_request_tx(wvif->wdev); } void wfx_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, From 1b38e0d042c87389209596cae91271f47ad72499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:28 +0000 Subject: [PATCH 302/353] staging: wfx: ensure that packet_id is unique MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In current code, packet_id is derivated from mac802.11 packet sequence number, but this number is only unique for a station. It is not sufficient. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-60-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/data_tx.c | 8 ++++++-- drivers/staging/wfx/wfx.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index c32994553633..20f4740734f2 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -469,8 +469,12 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, // Fill tx request req = (struct hif_req_tx *)hif_msg->body; - req->packet_id = queue_id << 16 | - IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + // packet_id just need to be unique on device. 32bits are more than + // necessary for that task, so we tae advantage of it to add some extra + // data for debug. + req->packet_id = queue_id << 28 | + IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)) << 16 | + (atomic_add_return(1, &wvif->wdev->packet_id) & 0xFFFF); req->data_flags.fc_offset = offset; if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) req->data_flags.after_dtim = 1; diff --git a/drivers/staging/wfx/wfx.h b/drivers/staging/wfx/wfx.h index 5d61946e33e0..8b85bb1abb9c 100644 --- a/drivers/staging/wfx/wfx.h +++ b/drivers/staging/wfx/wfx.h @@ -54,6 +54,7 @@ struct wfx_dev { int tx_burst_idx; atomic_t tx_lock; + atomic_t packet_id; u32 key_map; struct hif_req_add_key keys[MAX_KEY_ENTRIES]; From 1b72dee6f8764dc9fb869a6f7de2901b647646a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:30 +0000 Subject: [PATCH 303/353] staging: wfx: remove unused do_probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The identifier do_probe is unused since "staging: wfx: remove workaround to send probe requests" Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-61-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/queue.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index ec11a63a2ff9..c87d64fbb88f 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -365,7 +365,6 @@ static bool hif_handle_tx_data(struct wfx_vif *wvif, struct sk_buff *skb, struct ieee80211_hdr *frame = (struct ieee80211_hdr *) (req->frame + req->data_flags.fc_offset); enum { - do_probe, do_drop, do_wep, do_tx, From 7bc71e80bdaf623712352f25fba97a80716d7644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:31 +0000 Subject: [PATCH 304/353] staging: wfx: remove check for interface state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Obviously, the value of wvif->state as no reason to be wrong. At least, if it the case, dropping the frame is probably not the bast thing to do. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-62-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/queue.c | 50 +++++++++---------------------------- 1 file changed, 12 insertions(+), 38 deletions(-) diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index c87d64fbb88f..e0c609c35a7b 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -365,52 +365,26 @@ static bool hif_handle_tx_data(struct wfx_vif *wvif, struct sk_buff *skb, struct ieee80211_hdr *frame = (struct ieee80211_hdr *) (req->frame + req->data_flags.fc_offset); enum { - do_drop, do_wep, do_tx, } action = do_tx; - switch (wvif->vif->type) { - case NL80211_IFTYPE_STATION: - if (wvif->state < WFX_STATE_PRE_STA) - action = do_drop; - break; - case NL80211_IFTYPE_AP: - if (!wvif->state) - action = do_drop; - break; - case NL80211_IFTYPE_ADHOC: - if (wvif->state != WFX_STATE_IBSS) - action = do_drop; - break; - case NL80211_IFTYPE_MONITOR: - default: - action = do_drop; - break; - } - - if (action == do_tx) { - if (ieee80211_is_nullfunc(frame->frame_control)) { - mutex_lock(&wvif->bss_loss_lock); - if (wvif->bss_loss_state) { - wvif->bss_loss_confirm_id = req->packet_id; - req->queue_id.queue_id = HIF_QUEUE_ID_VOICE; - } - mutex_unlock(&wvif->bss_loss_lock); - } else if (ieee80211_has_protected(frame->frame_control) && - tx_priv->hw_key && - tx_priv->hw_key->keyidx != wvif->wep_default_key_id && - (tx_priv->hw_key->cipher == WLAN_CIPHER_SUITE_WEP40 || - tx_priv->hw_key->cipher == WLAN_CIPHER_SUITE_WEP104)) { - action = do_wep; + if (ieee80211_is_nullfunc(frame->frame_control)) { + mutex_lock(&wvif->bss_loss_lock); + if (wvif->bss_loss_state) { + wvif->bss_loss_confirm_id = req->packet_id; + req->queue_id.queue_id = HIF_QUEUE_ID_VOICE; } + mutex_unlock(&wvif->bss_loss_lock); + } else if (ieee80211_has_protected(frame->frame_control) && + tx_priv->hw_key && + tx_priv->hw_key->keyidx != wvif->wep_default_key_id && + (tx_priv->hw_key->cipher == WLAN_CIPHER_SUITE_WEP40 || + tx_priv->hw_key->cipher == WLAN_CIPHER_SUITE_WEP104)) { + action = do_wep; } switch (action) { - case do_drop: - wfx_pending_remove(wvif->wdev, skb); - handled = true; - break; case do_wep: wfx_tx_lock(wvif->wdev); WARN_ON(wvif->wep_pending_skb); From 5244357961a422100b73a9da423532578579324a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:34 +0000 Subject: [PATCH 305/353] staging: wfx: simplify hif_handle_tx_data() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since enum action has now only two cases, it can be dropped. Then hif_handle_tx_data() can be simplified. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-63-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/queue.c | 40 ++++++++++++++----------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index e0c609c35a7b..024497eb19ac 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -359,16 +359,13 @@ bool wfx_tx_queues_is_empty(struct wfx_dev *wdev) static bool hif_handle_tx_data(struct wfx_vif *wvif, struct sk_buff *skb, struct wfx_queue *queue) { - bool handled = false; - struct wfx_tx_priv *tx_priv = wfx_skb_tx_priv(skb); struct hif_req_tx *req = wfx_skb_txreq(skb); - struct ieee80211_hdr *frame = (struct ieee80211_hdr *) (req->frame + req->data_flags.fc_offset); - - enum { - do_wep, - do_tx, - } action = do_tx; + struct ieee80211_key_conf *hw_key = wfx_skb_tx_priv(skb)->hw_key; + struct ieee80211_hdr *frame = + (struct ieee80211_hdr *)(req->frame + req->data_flags.fc_offset); + // FIXME: mac80211 is smart enough to handle BSS loss. Driver should not + // try to do anything about that. if (ieee80211_is_nullfunc(frame->frame_control)) { mutex_lock(&wvif->bss_loss_lock); if (wvif->bss_loss_state) { @@ -376,31 +373,24 @@ static bool hif_handle_tx_data(struct wfx_vif *wvif, struct sk_buff *skb, req->queue_id.queue_id = HIF_QUEUE_ID_VOICE; } mutex_unlock(&wvif->bss_loss_lock); - } else if (ieee80211_has_protected(frame->frame_control) && - tx_priv->hw_key && - tx_priv->hw_key->keyidx != wvif->wep_default_key_id && - (tx_priv->hw_key->cipher == WLAN_CIPHER_SUITE_WEP40 || - tx_priv->hw_key->cipher == WLAN_CIPHER_SUITE_WEP104)) { - action = do_wep; } - switch (action) { - case do_wep: + // FIXME: identify the exact scenario matched by this condition. Does it + // happen yet? + if (ieee80211_has_protected(frame->frame_control) && + hw_key && hw_key->keyidx != wvif->wep_default_key_id && + (hw_key->cipher == WLAN_CIPHER_SUITE_WEP40 || + hw_key->cipher == WLAN_CIPHER_SUITE_WEP104)) { wfx_tx_lock(wvif->wdev); WARN_ON(wvif->wep_pending_skb); - wvif->wep_default_key_id = tx_priv->hw_key->keyidx; + wvif->wep_default_key_id = hw_key->keyidx; wvif->wep_pending_skb = skb; if (!schedule_work(&wvif->wep_key_work)) wfx_tx_unlock(wvif->wdev); - handled = true; - break; - case do_tx: - break; - default: - /* Do nothing */ - break; + return true; + } else { + return false; } - return handled; } static int wfx_get_prio_queue(struct wfx_vif *wvif, From 2f5fd8b07745838e590b61d5b136be8b9f94cc4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:35 +0000 Subject: [PATCH 306/353] staging: wfx: simplify wfx_tx_queue_get_num_queued() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wfx_tx_queue_get_num_queued() can take advantage of BIT() instead of maintaining one variable for a counter and another for a mask. In add, wfx_tx_queue_get_num_queued() has no real reason to return a size_t instead of an int. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-64-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/queue.c | 14 +++++--------- drivers/staging/wfx/queue.h | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index 024497eb19ac..0bcc61feee1d 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -175,11 +175,9 @@ void wfx_tx_queues_deinit(struct wfx_dev *wdev) wfx_tx_queues_clear(wdev); } -size_t wfx_tx_queue_get_num_queued(struct wfx_queue *queue, - u32 link_id_map) +int wfx_tx_queue_get_num_queued(struct wfx_queue *queue, u32 link_id_map) { - size_t ret; - int i, bit; + int ret, i; if (!link_id_map) return 0; @@ -189,11 +187,9 @@ size_t wfx_tx_queue_get_num_queued(struct wfx_queue *queue, ret = skb_queue_len(&queue->queue); } else { ret = 0; - for (i = 0, bit = 1; i < ARRAY_SIZE(queue->link_map_cache); - ++i, bit <<= 1) { - if (link_id_map & bit) + for (i = 0; i < ARRAY_SIZE(queue->link_map_cache); i++) + if (link_id_map & BIT(i)) ret += queue->link_map_cache[i]; - } } spin_unlock_bh(&queue->queue.lock); return ret; @@ -555,7 +551,7 @@ struct hif_msg *wfx_tx_queues_get(struct wfx_dev *wdev) /* allow bursting if txop is set */ if (wvif->edca_params[queue_num].txop) - burst = (int)wfx_tx_queue_get_num_queued(queue, tx_allowed_mask) + 1; + burst = wfx_tx_queue_get_num_queued(queue, tx_allowed_mask) + 1; else burst = 1; diff --git a/drivers/staging/wfx/queue.h b/drivers/staging/wfx/queue.h index 096ae86135cc..90bb060d1204 100644 --- a/drivers/staging/wfx/queue.h +++ b/drivers/staging/wfx/queue.h @@ -51,7 +51,7 @@ struct hif_msg *wfx_tx_queues_get_after_dtim(struct wfx_vif *wvif); void wfx_tx_queue_put(struct wfx_dev *wdev, struct wfx_queue *queue, struct sk_buff *skb); -size_t wfx_tx_queue_get_num_queued(struct wfx_queue *queue, u32 link_id_map); +int wfx_tx_queue_get_num_queued(struct wfx_queue *queue, u32 link_id_map); struct sk_buff *wfx_pending_get(struct wfx_dev *wdev, u32 packet_id); int wfx_pending_remove(struct wfx_dev *wdev, struct sk_buff *skb); From 240503a6e3629e0d32e1b93c648fabb5b37e9122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:37 +0000 Subject: [PATCH 307/353] staging: wfx: simplify hif_multi_tx_confirm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Usage of the "buf_loc" variable does not simplify the function. Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-65-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/hif_rx.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/staging/wfx/hif_rx.c b/drivers/staging/wfx/hif_rx.c index f798cd6973b6..33c22c5d629d 100644 --- a/drivers/staging/wfx/hif_rx.c +++ b/drivers/staging/wfx/hif_rx.c @@ -77,21 +77,16 @@ static int hif_multi_tx_confirm(struct wfx_dev *wdev, const struct hif_msg *hif, const void *buf) { const struct hif_cnf_multi_transmit *body = buf; - const struct hif_cnf_tx *buf_loc = - (const struct hif_cnf_tx *)&body->tx_conf_payload; struct wfx_vif *wvif = wdev_to_wvif(wdev, hif->interface); - int count = body->num_tx_confs; int i; - WARN(count <= 0, "corrupted message"); + WARN(body->num_tx_confs <= 0, "corrupted message"); WARN_ON(!wvif); if (!wvif) return -EFAULT; - for (i = 0; i < count; ++i) { - wfx_tx_confirm_cb(wvif, buf_loc); - buf_loc++; - } + for (i = 0; i < body->num_tx_confs; i++) + wfx_tx_confirm_cb(wvif, &body->tx_conf_payload[i]); return 0; } From 270f104ba26f0498aff85e5b002e2f4c2249c04b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= Date: Wed, 15 Jan 2020 13:55:38 +0000 Subject: [PATCH 308/353] staging: wfx: update TODO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some work has been done :) Signed-off-by: Jérôme Pouiller Link: https://lore.kernel.org/r/20200115135338.14374-66-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wfx/TODO | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/staging/wfx/TODO b/drivers/staging/wfx/TODO index 6b1cdd24afc9..efcb7c6a5aa7 100644 --- a/drivers/staging/wfx/TODO +++ b/drivers/staging/wfx/TODO @@ -1,18 +1,8 @@ This is a list of things that need to be done to get this driver out of the staging directory. - - Allocation of "link ids" is too complex. Allocation/release of link ids from - sta_add()/sta_remove() should be sufficient. - - - The path for packets with IEEE80211_TX_CTL_SEND_AFTER_DTIM flags should be - cleaned up. Currently, the process involve multiple work structs and a - timer. It could be simplifed. In add, the requeue mechanism triggers more - frequently than it should. - - All structures defined in hif_api_*.h are intended to sent/received to/from - hardware. All their members whould be declared __le32 or __le16. These - structs should only been used in files named hif_* (and maybe in data_*.c). - The upper layers (sta.c, scan.c etc...) should manage mac80211 structures. + hardware. All their members whould be declared __le32 or __le16. See: https://lore.kernel.org/lkml/20191111202852.GX26530@ZenIV.linux.org.uk From da4d3d6bb9f6047217d549c233303161bb4678d9 Mon Sep 17 00:00:00 2001 From: Alexandru Tachici Date: Mon, 13 Jan 2020 12:26:52 +0200 Subject: [PATCH 309/353] iio: adc: ad-sigma-delta: Allow custom IRQ flags Before this patch the ad_sigma_delta implementation hardcoded the irq trigger type to low, assuming that all Sigma-Delta ADCs have the same interrupt-type. This patch allows all drivers using the ad_sigma_delta layer to set the irq trigger type to the one specified in the datasheet. Signed-off-by: Alexandru Tachici Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7124.c | 2 ++ drivers/iio/adc/ad7780.c | 1 + drivers/iio/adc/ad7791.c | 1 + drivers/iio/adc/ad7793.c | 1 + drivers/iio/adc/ad_sigma_delta.c | 2 +- include/linux/iio/adc/ad_sigma_delta.h | 2 ++ 6 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 3f03abf100b5..63df2e2a8caf 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -224,6 +225,7 @@ static const struct ad_sigma_delta_info ad7124_sigma_delta_info = { .addr_shift = 0, .read_mask = BIT(6), .data_reg = AD7124_DATA, + .irq_flags = IRQF_TRIGGER_LOW, }; static int ad7124_set_channel_odr(struct ad7124_state *st, diff --git a/drivers/iio/adc/ad7780.c b/drivers/iio/adc/ad7780.c index 217a5a5c3c6d..291c1a898129 100644 --- a/drivers/iio/adc/ad7780.c +++ b/drivers/iio/adc/ad7780.c @@ -203,6 +203,7 @@ static const struct ad_sigma_delta_info ad7780_sigma_delta_info = { .set_mode = ad7780_set_mode, .postprocess_sample = ad7780_postprocess_sample, .has_registers = false, + .irq_flags = IRQF_TRIGGER_LOW, }; #define AD7780_CHANNEL(bits, wordsize) \ diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index 54025ea10239..abb239392631 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -205,6 +205,7 @@ static const struct ad_sigma_delta_info ad7791_sigma_delta_info = { .has_registers = true, .addr_shift = 4, .read_mask = BIT(3), + .irq_flags = IRQF_TRIGGER_LOW, }; static int ad7791_read_raw(struct iio_dev *indio_dev, diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index bbc41ecf0d2f..b747db97f78a 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -206,6 +206,7 @@ static const struct ad_sigma_delta_info ad7793_sigma_delta_info = { .has_registers = true, .addr_shift = 3, .read_mask = BIT(6), + .irq_flags = IRQF_TRIGGER_LOW, }; static const struct ad_sd_calib_data ad7793_calib_arr[6] = { diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index 8ba90486c787..8115b6de1d6c 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -500,7 +500,7 @@ static int ad_sd_probe_trigger(struct iio_dev *indio_dev) ret = request_irq(sigma_delta->spi->irq, ad_sd_data_rdy_trig_poll, - IRQF_TRIGGER_LOW, + sigma_delta->info->irq_flags, indio_dev->name, sigma_delta); if (ret) diff --git a/include/linux/iio/adc/ad_sigma_delta.h b/include/linux/iio/adc/ad_sigma_delta.h index 8a4e25a7080c..5a127c0ed200 100644 --- a/include/linux/iio/adc/ad_sigma_delta.h +++ b/include/linux/iio/adc/ad_sigma_delta.h @@ -40,6 +40,7 @@ struct iio_dev; * @read_mask: Mask for the communications register having the read bit set. * @data_reg: Address of the data register, if 0 the default address of 0x3 will * be used. + * @irq_flags: flags for the interrupt used by the triggered buffer */ struct ad_sigma_delta_info { int (*set_channel)(struct ad_sigma_delta *, unsigned int channel); @@ -49,6 +50,7 @@ struct ad_sigma_delta_info { unsigned int addr_shift; unsigned int read_mask; unsigned int data_reg; + unsigned long irq_flags; }; /** From 79ef91493f5494e9ddbad85bf571ec03940a7f5c Mon Sep 17 00:00:00 2001 From: Alexandru Tachici Date: Mon, 13 Jan 2020 12:26:53 +0200 Subject: [PATCH 310/353] iio: adc: ad7124: Set IRQ type to falling Ad7124 data-sheet specifies that the falling edge of the DOUT line should be used for an interrupt. The current irq flag (IRQF_TRIGGER_LOW) used will cause unwanted behaviour. When enabling the interrupt it will fire once because the DOUT line is already low. This will make the driver to read an unfinished conversion from the chip. This patch sets the irq type to the one specified in the data-sheet. Signed-off-by: Alexandru Tachici Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7124.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 63df2e2a8caf..52f45b13da4a 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -225,7 +225,7 @@ static const struct ad_sigma_delta_info ad7124_sigma_delta_info = { .addr_shift = 0, .read_mask = BIT(6), .data_reg = AD7124_DATA, - .irq_flags = IRQF_TRIGGER_LOW, + .irq_flags = IRQF_TRIGGER_FALLING, }; static int ad7124_set_channel_odr(struct ad7124_state *st, From 608184788502fd475e7bca4b1692fda5f0fef5b6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 15 Jan 2020 19:44:24 +0200 Subject: [PATCH 311/353] iio: magnetometer: ak8975: Get rid of platform data Since IIO framework supports device property API and driver has been moved already to the use of GPIO descriptors the logical continuation is to get rid of platform data completely. We are on the safe side here since there are no users of it in the kernel. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 14 +++----------- include/linux/iio/magnetometer/ak8975.h | 15 --------------- 2 files changed, 3 insertions(+), 26 deletions(-) delete mode 100644 include/linux/iio/magnetometer/ak8975.h diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 55cffaa82456..8e50e073bcbf 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -28,8 +28,6 @@ #include #include -#include - /* * Register definitions, as well as various shifts and masks to get at the * individual fields of the registers. @@ -857,8 +855,6 @@ static int ak8975_probe(struct i2c_client *client, int err; const char *name = NULL; enum asahi_compass_chipset chipset = AK_MAX_TYPE; - const struct ak8975_platform_data *pdata = - dev_get_platdata(&client->dev); /* * Grab and set up the supplied GPIO. @@ -883,13 +879,9 @@ static int ak8975_probe(struct i2c_client *client, data->eoc_gpiod = eoc_gpiod; data->eoc_irq = 0; - if (!pdata) { - err = iio_read_mount_matrix(&client->dev, "mount-matrix", - &data->orientation); - if (err) - return err; - } else - data->orientation = pdata->orientation; + err = iio_read_mount_matrix(&client->dev, "mount-matrix", &data->orientation); + if (err) + return err; /* id will be NULL when enumerated via ACPI */ if (id) { diff --git a/include/linux/iio/magnetometer/ak8975.h b/include/linux/iio/magnetometer/ak8975.h deleted file mode 100644 index df3697183800..000000000000 --- a/include/linux/iio/magnetometer/ak8975.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __IIO_MAGNETOMETER_AK8975_H__ -#define __IIO_MAGNETOMETER_AK8975_H__ - -#include - -/** - * struct ak8975_platform_data - AK8975 magnetometer driver platform data - * @orientation: mounting matrix relative to main hardware - */ -struct ak8975_platform_data { - struct iio_mount_matrix orientation; -}; - -#endif From 71f221f8a0cd73f985e37d8a05dea2d63eb95b71 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 15 Jan 2020 19:44:25 +0200 Subject: [PATCH 312/353] iio: magnetometer: ak8975: Convert to use device_get_match_data() Convert to use device_get_match_data() instead of open coded variant. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 39 +++++++++++++------------------ 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 8e50e073bcbf..3c881541ae72 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -203,11 +203,11 @@ static long ak09912_raw_to_gauss(u16 data) /* Compatible Asahi Kasei Compass parts */ enum asahi_compass_chipset { + AKXXXX = 0, AK8975, AK8963, AK09911, AK09912, - AK_MAX_TYPE }; enum ak_ctrl_reg_addr { @@ -245,7 +245,7 @@ struct ak_def { u8 data_regs[3]; }; -static const struct ak_def ak_def_array[AK_MAX_TYPE] = { +static const struct ak_def ak_def_array[] = { { .type = AK8975, .raw_to_gauss = ak8975_raw_to_gauss, @@ -781,19 +781,6 @@ static const struct acpi_device_id ak_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, ak_acpi_match); #endif -static const char *ak8975_match_acpi_device(struct device *dev, - enum asahi_compass_chipset *chipset) -{ - const struct acpi_device_id *id; - - id = acpi_match_device(dev->driver->acpi_match_table, dev); - if (!id) - return NULL; - *chipset = (int)id->driver_data; - - return dev_name(dev); -} - static void ak8975_fill_buffer(struct iio_dev *indio_dev) { struct ak8975_data *data = iio_priv(indio_dev); @@ -852,9 +839,11 @@ static int ak8975_probe(struct i2c_client *client, struct ak8975_data *data; struct iio_dev *indio_dev; struct gpio_desc *eoc_gpiod; + const void *match; + unsigned int i; int err; + enum asahi_compass_chipset chipset; const char *name = NULL; - enum asahi_compass_chipset chipset = AK_MAX_TYPE; /* * Grab and set up the supplied GPIO. @@ -884,23 +873,27 @@ static int ak8975_probe(struct i2c_client *client, return err; /* id will be NULL when enumerated via ACPI */ - if (id) { + match = device_get_match_data(&client->dev); + if (match) { + chipset = (enum asahi_compass_chipset)(match); + name = dev_name(&client->dev); + } else if (id) { chipset = (enum asahi_compass_chipset)(id->driver_data); name = id->name; - } else if (ACPI_HANDLE(&client->dev)) { - name = ak8975_match_acpi_device(&client->dev, &chipset); - if (!name) - return -ENODEV; } else return -ENOSYS; - if (chipset >= AK_MAX_TYPE) { + for (i = 0; i < ARRAY_SIZE(ak_def_array); i++) + if (ak_def_array[i].type == chipset) + break; + + if (i == ARRAY_SIZE(ak_def_array)) { dev_err(&client->dev, "AKM device type unsupported: %d\n", chipset); return -ENODEV; } - data->def = &ak_def_array[chipset]; + data->def = &ak_def_array[i]; /* Fetch the regulators */ data->vdd = devm_regulator_get(&client->dev, "vdd"); From 2e4c0a5e25768097ecdb514ef453b423e932beea Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Maneyrol Date: Thu, 16 Jan 2020 18:56:45 +0100 Subject: [PATCH 313/353] iio: imu: inv_mpu6050: add fifo temperature data support Add support of temperature data in fifo for all chips. Enable unification of scan elements for icm20602. Add macros for generating scan elements. Signed-off-by: Jean-Baptiste Maneyrol Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 200 +++++++----------- drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 22 +- drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 6 +- drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 3 + 4 files changed, 90 insertions(+), 141 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 268240644adf..1eb3c263b528 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -104,6 +104,7 @@ static const struct inv_mpu6050_chip_config chip_config_6050 = { .divider = INV_MPU6050_FIFO_RATE_TO_DIVIDER(INV_MPU6050_INIT_FIFO_RATE), .gyro_fifo_enable = false, .accl_fifo_enable = false, + .temp_fifo_enable = false, .magn_fifo_enable = false, .accl_fs = INV_MPU6050_FS_02G, .user_ctrl = 0, @@ -856,19 +857,27 @@ static const struct iio_chan_spec_ext_info inv_ext_info[] = { .ext_info = inv_ext_info, \ } +#define INV_MPU6050_TEMP_CHAN(_index) \ + { \ + .type = IIO_TEMP, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ + | BIT(IIO_CHAN_INFO_OFFSET) \ + | BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .shift = 0, \ + .endianness = IIO_BE, \ + }, \ + } + static const struct iio_chan_spec inv_mpu_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP), - /* - * Note that temperature should only be via polled reading only, - * not the final scan elements output. - */ - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_OFFSET) - | BIT(IIO_CHAN_INFO_SCALE), - .scan_index = -1, - }, + + INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), @@ -878,22 +887,29 @@ static const struct iio_chan_spec inv_mpu_channels[] = { INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z), }; +#define INV_MPU6050_SCAN_MASK_3AXIS_ACCEL \ + (BIT(INV_MPU6050_SCAN_ACCL_X) \ + | BIT(INV_MPU6050_SCAN_ACCL_Y) \ + | BIT(INV_MPU6050_SCAN_ACCL_Z)) + +#define INV_MPU6050_SCAN_MASK_3AXIS_GYRO \ + (BIT(INV_MPU6050_SCAN_GYRO_X) \ + | BIT(INV_MPU6050_SCAN_GYRO_Y) \ + | BIT(INV_MPU6050_SCAN_GYRO_Z)) + +#define INV_MPU6050_SCAN_MASK_TEMP (BIT(INV_MPU6050_SCAN_TEMP)) + static const unsigned long inv_mpu_scan_masks[] = { /* 3-axis accel */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_TEMP, /* 3-axis gyro */ - BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z), + INV_MPU6050_SCAN_MASK_3AXIS_GYRO, + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis accel + gyro */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z) - | BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU6050_SCAN_MASK_TEMP, 0, }; @@ -917,17 +933,9 @@ static const unsigned long inv_mpu_scan_masks[] = { static const struct iio_chan_spec inv_mpu9150_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP), - /* - * Note that temperature should only be via polled reading only, - * not the final scan elements output. - */ - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_OFFSET) - | BIT(IIO_CHAN_INFO_SCALE), - .scan_index = -1, - }, + + INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), @@ -944,17 +952,9 @@ static const struct iio_chan_spec inv_mpu9150_channels[] = { static const struct iio_chan_spec inv_mpu9250_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP), - /* - * Note that temperature should only be via polled reading only, - * not the final scan elements output. - */ - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_OFFSET) - | BIT(IIO_CHAN_INFO_SCALE), - .scan_index = -1, - }, + + INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), @@ -969,98 +969,50 @@ static const struct iio_chan_spec inv_mpu9250_channels[] = { INV_MPU9X50_MAGN_CHAN(IIO_MOD_Z, 16, INV_MPU9X50_SCAN_MAGN_Z), }; +#define INV_MPU9X50_SCAN_MASK_3AXIS_MAGN \ + (BIT(INV_MPU9X50_SCAN_MAGN_X) \ + | BIT(INV_MPU9X50_SCAN_MAGN_Y) \ + | BIT(INV_MPU9X50_SCAN_MAGN_Z)) + static const unsigned long inv_mpu9x50_scan_masks[] = { /* 3-axis accel */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_TEMP, /* 3-axis gyro */ - BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z), + INV_MPU6050_SCAN_MASK_3AXIS_GYRO, + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU6050_SCAN_MASK_TEMP, /* 3-axis magn */ - BIT(INV_MPU9X50_SCAN_MAGN_X) - | BIT(INV_MPU9X50_SCAN_MAGN_Y) - | BIT(INV_MPU9X50_SCAN_MAGN_Z), + INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, + INV_MPU9X50_SCAN_MASK_3AXIS_MAGN | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis accel + gyro */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z) - | BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis accel + magn */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z) - | BIT(INV_MPU9X50_SCAN_MAGN_X) - | BIT(INV_MPU9X50_SCAN_MAGN_Y) - | BIT(INV_MPU9X50_SCAN_MAGN_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN + | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis gyro + magn */ - BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z) - | BIT(INV_MPU9X50_SCAN_MAGN_X) - | BIT(INV_MPU9X50_SCAN_MAGN_Y) - | BIT(INV_MPU9X50_SCAN_MAGN_Z), + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN + | INV_MPU6050_SCAN_MASK_TEMP, /* 9-axis accel + gyro + magn */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z) - | BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z) - | BIT(INV_MPU9X50_SCAN_MAGN_X) - | BIT(INV_MPU9X50_SCAN_MAGN_Y) - | BIT(INV_MPU9X50_SCAN_MAGN_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN + | INV_MPU6050_SCAN_MASK_TEMP, 0, }; -static const struct iio_chan_spec inv_icm20602_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(INV_ICM20602_SCAN_TIMESTAMP), - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_OFFSET) - | BIT(IIO_CHAN_INFO_SCALE), - .scan_index = INV_ICM20602_SCAN_TEMP, - .scan_type = { - .sign = 's', - .realbits = 16, - .storagebits = 16, - .shift = 0, - .endianness = IIO_BE, - }, - }, - - INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_ICM20602_SCAN_GYRO_X), - INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_ICM20602_SCAN_GYRO_Y), - INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_ICM20602_SCAN_GYRO_Z), - - INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_ICM20602_SCAN_ACCL_Y), - INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_ICM20602_SCAN_ACCL_X), - INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_ICM20602_SCAN_ACCL_Z), -}; - static const unsigned long inv_icm20602_scan_masks[] = { /* 3-axis accel + temp (mandatory) */ - BIT(INV_ICM20602_SCAN_ACCL_X) - | BIT(INV_ICM20602_SCAN_ACCL_Y) - | BIT(INV_ICM20602_SCAN_ACCL_Z) - | BIT(INV_ICM20602_SCAN_TEMP), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_TEMP, /* 3-axis gyro + temp (mandatory) */ - BIT(INV_ICM20602_SCAN_GYRO_X) - | BIT(INV_ICM20602_SCAN_GYRO_Y) - | BIT(INV_ICM20602_SCAN_GYRO_Z) - | BIT(INV_ICM20602_SCAN_TEMP), + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis accel + gyro + temp (mandatory) */ - BIT(INV_ICM20602_SCAN_ACCL_X) - | BIT(INV_ICM20602_SCAN_ACCL_Y) - | BIT(INV_ICM20602_SCAN_ACCL_Z) - | BIT(INV_ICM20602_SCAN_GYRO_X) - | BIT(INV_ICM20602_SCAN_GYRO_Y) - | BIT(INV_ICM20602_SCAN_GYRO_Z) - | BIT(INV_ICM20602_SCAN_TEMP), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU6050_SCAN_MASK_TEMP, 0, }; @@ -1363,8 +1315,8 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, indio_dev->available_scan_masks = inv_mpu9x50_scan_masks; break; case INV_ICM20602: - indio_dev->channels = inv_icm20602_channels; - indio_dev->num_channels = ARRAY_SIZE(inv_icm20602_channels); + indio_dev->channels = inv_mpu_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); indio_dev->available_scan_masks = inv_icm20602_scan_masks; break; default: diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index b096e010d4ee..6158fca7f70e 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -86,6 +86,7 @@ enum inv_devices { * @accl_fs: accel full scale range. * @accl_fifo_enable: enable accel data output * @gyro_fifo_enable: enable gyro data output + * @temp_fifo_enable: enable temp data output * @magn_fifo_enable: enable magn data output * @divider: chip sample rate divider (sample rate divider - 1) */ @@ -95,6 +96,7 @@ struct inv_mpu6050_chip_config { unsigned int accl_fs:2; unsigned int accl_fifo_enable:1; unsigned int gyro_fifo_enable:1; + unsigned int temp_fifo_enable:1; unsigned int magn_fifo_enable:1; u8 divider; u8 user_ctrl; @@ -184,6 +186,7 @@ struct inv_mpu6050_state { #define INV_MPU6050_BIT_SLAVE_2 0x04 #define INV_MPU6050_BIT_ACCEL_OUT 0x08 #define INV_MPU6050_BITS_GYRO_OUT 0x70 +#define INV_MPU6050_BIT_TEMP_OUT 0x80 #define INV_MPU6050_REG_I2C_MST_CTRL 0x24 #define INV_MPU6050_BITS_I2C_MST_CLK_400KHZ 0x0D @@ -268,8 +271,8 @@ struct inv_mpu6050_state { /* MPU9X50 9-axis magnetometer */ #define INV_MPU9X50_BYTES_MAGN 7 -/* ICM20602 FIFO samples include temperature readings */ -#define INV_ICM20602_BYTES_PER_TEMP_SENSOR 2 +/* FIFO temperature sample size */ +#define INV_MPU6050_BYTES_PER_TEMP_SENSOR 2 /* mpu6500 registers */ #define INV_MPU6500_REG_ACCEL_CONFIG_2 0x1D @@ -298,7 +301,7 @@ struct inv_mpu6050_state { #define INV_ICM20608_TEMP_OFFSET 8170 #define INV_ICM20608_TEMP_SCALE 3059976 -/* 6 + 6 + 7 (for MPU9x50) = 19 round up to 24 and plus 8 */ +/* 6 + 6 + 2 + 7 (for MPU9x50) = 21 round up to 24 and plus 8 */ #define INV_MPU6050_OUTPUT_DATA_SIZE 32 #define INV_MPU6050_REG_INT_PIN_CFG 0x37 @@ -344,6 +347,7 @@ enum inv_mpu6050_scan { INV_MPU6050_SCAN_ACCL_X, INV_MPU6050_SCAN_ACCL_Y, INV_MPU6050_SCAN_ACCL_Z, + INV_MPU6050_SCAN_TEMP, INV_MPU6050_SCAN_GYRO_X, INV_MPU6050_SCAN_GYRO_Y, INV_MPU6050_SCAN_GYRO_Z, @@ -355,18 +359,6 @@ enum inv_mpu6050_scan { INV_MPU9X50_SCAN_TIMESTAMP, }; -/* scan element definition for ICM20602, which includes temperature */ -enum inv_icm20602_scan { - INV_ICM20602_SCAN_ACCL_X, - INV_ICM20602_SCAN_ACCL_Y, - INV_ICM20602_SCAN_ACCL_Z, - INV_ICM20602_SCAN_TEMP, - INV_ICM20602_SCAN_GYRO_X, - INV_ICM20602_SCAN_GYRO_Y, - INV_ICM20602_SCAN_GYRO_Z, - INV_ICM20602_SCAN_TIMESTAMP, -}; - enum inv_mpu6050_filter_e { INV_MPU6050_FILTER_256HZ_NOLPF2 = 0, INV_MPU6050_FILTER_188HZ, diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index 10d16ec5104b..3755577dc449 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -142,6 +142,8 @@ int inv_reset_fifo(struct iio_dev *indio_dev) d |= INV_MPU6050_BITS_GYRO_OUT; if (st->chip_config.accl_fifo_enable) d |= INV_MPU6050_BIT_ACCEL_OUT; + if (st->chip_config.temp_fifo_enable) + d |= INV_MPU6050_BIT_TEMP_OUT; if (st->chip_config.magn_fifo_enable) d |= INV_MPU6050_BIT_SLAVE_0; result = regmap_write(st->map, st->reg->fifo_en, d); @@ -200,8 +202,8 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) if (st->chip_config.gyro_fifo_enable) bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR; - if (st->chip_type == INV_ICM20602) - bytes_per_datum += INV_ICM20602_BYTES_PER_TEMP_SENSOR; + if (st->chip_config.temp_fifo_enable) + bytes_per_datum += INV_MPU6050_BYTES_PER_TEMP_SENSOR; if (st->chip_config.magn_fifo_enable) bytes_per_datum += INV_MPU9X50_BYTES_MAGN; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c index a9c75bc62f18..5199fe790c30 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c @@ -24,6 +24,9 @@ static void inv_scan_query_mpu6050(struct iio_dev *indio_dev) indio_dev->active_scan_mask) || test_bit(INV_MPU6050_SCAN_ACCL_Z, indio_dev->active_scan_mask); + + st->chip_config.temp_fifo_enable = + test_bit(INV_MPU6050_SCAN_TEMP, indio_dev->active_scan_mask); } static void inv_scan_query_mpu9x50(struct iio_dev *indio_dev) From 84961af78c509d500b9b4a45989e449f048c821a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= Date: Sat, 11 Jan 2020 16:19:11 +0100 Subject: [PATCH 314/353] iio: imu/mpu6050: support dual-edge IRQ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make mpu6050 usable on platforms which provide only any-edge interrupts. One example of this kind of platform is AT91SAM9G45 Signed-off-by: MichaÅ‚ MirosÅ‚aw Acked-by: Jean-Baptiste Maneyrol Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 2 +- drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 1eb3c263b528..5096fc49012d 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -1220,7 +1220,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, irq_type = irqd_get_trigger_type(desc); if (!irq_type) irq_type = IRQF_TRIGGER_RISING; - if (irq_type == IRQF_TRIGGER_RISING) + if (irq_type & IRQF_TRIGGER_RISING) // rising or both-edge st->irq_mask = INV_MPU6050_ACTIVE_HIGH; else if (irq_type == IRQF_TRIGGER_FALLING) st->irq_mask = INV_MPU6050_ACTIVE_LOW; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index 3755577dc449..f9fdf4302a91 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -185,11 +185,8 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) "failed to ack interrupt\n"); goto flush_fifo; } - if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) { - dev_warn(regmap_get_device(st->map), - "spurious interrupt with status 0x%x\n", int_status); + if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) goto end_session; - } if (!(st->chip_config.accl_fifo_enable | st->chip_config.gyro_fifo_enable | From 98496ccdf0dd88696203e69542e07ef824c56ead Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 16 Jan 2020 13:08:29 +0300 Subject: [PATCH 315/353] iio: accel: bma400: prevent setting accel scale too low This puts an upper bound on "val2" but it also needs to have a lower bound (BMA400_SCALE_MIN). Fixes: 465c811f1f20 ("iio: accel: Add driver for the BMA400") Signed-off-by: Dan Carpenter Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma400_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c index ab4a158b35af..cc77f89c048b 100644 --- a/drivers/iio/accel/bma400_core.c +++ b/drivers/iio/accel/bma400_core.c @@ -752,7 +752,8 @@ static int bma400_write_raw(struct iio_dev *indio_dev, mutex_unlock(&data->mutex); return ret; case IIO_CHAN_INFO_SCALE: - if (val != 0 || val2 > BMA400_SCALE_MAX) + if (val != 0 || + val2 < BMA400_SCALE_MIN || val2 > BMA400_SCALE_MAX) return -EINVAL; mutex_lock(&data->mutex); From 80cbc848c4fa03580954ab6598e415b6b56a66ac Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Thu, 16 Jan 2020 15:11:47 +0200 Subject: [PATCH 316/353] iio: imu: adis16480: Add support for ADIS16490 The ADIS16490 is part of the same family with ADIS16495 and ADIS16497, the main difference is the temperature, accelerometer and gyroscope scales. Datasheet: Link: https://www.analog.com/media/en/technical-documentation/data-sheets/adis16490.pdf Signed-off-by: Stefan Popa Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis16480.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index f0ad7ce64861..dac87f1001fd 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -787,6 +787,7 @@ enum adis16480_variant { ADIS16480, ADIS16485, ADIS16488, + ADIS16490, ADIS16495_1, ADIS16495_2, ADIS16495_3, @@ -878,6 +879,20 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .filter_freqs = adis16480_def_filter_freqs, .timeouts = &adis16485_timeouts, }, + [ADIS16490] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), + .gyro_max_val = 20000 << 16, + .gyro_max_scale = IIO_DEGREE_TO_RAD(100), + .accel_max_val = IIO_M_S_2_TO_G(16000 << 16), + .accel_max_scale = 8, + .temp_scale = 14285, /* 14.285 milli degree Celsius */ + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + .timeouts = &adis16495_timeouts, + }, [ADIS16495_1] = { .channels = adis16485_channels, .num_channels = ARRAY_SIZE(adis16485_channels), @@ -1341,6 +1356,7 @@ static const struct spi_device_id adis16480_ids[] = { { "adis16480", ADIS16480 }, { "adis16485", ADIS16485 }, { "adis16488", ADIS16488 }, + { "adis16490", ADIS16490 }, { "adis16495-1", ADIS16495_1 }, { "adis16495-2", ADIS16495_2 }, { "adis16495-3", ADIS16495_3 }, @@ -1356,6 +1372,7 @@ static const struct of_device_id adis16480_of_match[] = { { .compatible = "adi,adis16480" }, { .compatible = "adi,adis16485" }, { .compatible = "adi,adis16488" }, + { .compatible = "adi,adis16490" }, { .compatible = "adi,adis16495-1" }, { .compatible = "adi,adis16495-2" }, { .compatible = "adi,adis16495-3" }, From 49576627b33496651d5f30ec79e164c6ba6f0410 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Thu, 16 Jan 2020 15:11:48 +0200 Subject: [PATCH 317/353] dt-bindings: iio: adis16480: add compatible entry for ADIS16490 This change adds an entry for ADIS16490 in the list of compatible devices defined in the dt-bindings of the adis16480 driver. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/imu/adi,adis16480.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/iio/imu/adi,adis16480.txt b/Documentation/devicetree/bindings/iio/imu/adi,adis16480.txt index ed7783f45233..cd903a1d880d 100644 --- a/Documentation/devicetree/bindings/iio/imu/adi,adis16480.txt +++ b/Documentation/devicetree/bindings/iio/imu/adi,adis16480.txt @@ -8,6 +8,7 @@ Required properties for the ADIS16480: * "adi,adis16480" * "adi,adis16485" * "adi,adis16488" + * "adi,adis16490" * "adi,adis16495-1" * "adi,adis16495-2" * "adi,adis16495-3" From 622b4339f93e2c2641919d405cd15e1d256f8fd3 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 13 Jan 2020 14:18:59 +0100 Subject: [PATCH 318/353] iio: adc: stm32-adc: don't print an error on probe deferral Do not print an error trace when deferring probe for some resource. Signed-off-by: Etienne Carriere Signed-off-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-adc-core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 97655d7fc11a..2df88d2b880a 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -688,7 +688,8 @@ static int stm32_adc_probe(struct platform_device *pdev) priv->vref = devm_regulator_get(&pdev->dev, "vref"); if (IS_ERR(priv->vref)) { ret = PTR_ERR(priv->vref); - dev_err(&pdev->dev, "vref get failed, %d\n", ret); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "vref get failed, %d\n", ret); return ret; } @@ -696,7 +697,8 @@ static int stm32_adc_probe(struct platform_device *pdev) if (IS_ERR(priv->aclk)) { ret = PTR_ERR(priv->aclk); if (ret != -ENOENT) { - dev_err(&pdev->dev, "Can't get 'adc' clock\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Can't get 'adc' clock\n"); return ret; } priv->aclk = NULL; @@ -706,7 +708,8 @@ static int stm32_adc_probe(struct platform_device *pdev) if (IS_ERR(priv->bclk)) { ret = PTR_ERR(priv->bclk); if (ret != -ENOENT) { - dev_err(&pdev->dev, "Can't get 'bus' clock\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Can't get 'bus' clock\n"); return ret; } priv->bclk = NULL; From 04e6fedb18f6899453e59a748fb95be56ef73836 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Mon, 13 Jan 2020 11:11:40 +0100 Subject: [PATCH 319/353] iio: imu: st_lsm6dsx: add mount matrix support Allow to read the mount-matrix device tree property and provide the mount_matrix file for userspace to read. Signed-off-by: Martin Kepplinger Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 19 +++++++++++++++++++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index c08f57226ebb..9c3486a8134f 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -76,6 +76,7 @@ enum st_lsm6dsx_hw_id { .endianness = IIO_LE, \ }, \ .event_spec = &st_lsm6dsx_event, \ + .ext_info = st_lsm6dsx_accel_ext_info, \ .num_event_specs = 1, \ } @@ -378,6 +379,7 @@ struct st_lsm6dsx_sensor { * @enable_event: enabled event bitmask. * @iio_devs: Pointers to acc/gyro iio_dev instances. * @settings: Pointer to the specific sensor settings in use. + * @orientation: sensor chip orientation relative to main hardware. */ struct st_lsm6dsx_hw { struct device *dev; @@ -404,6 +406,8 @@ struct st_lsm6dsx_hw { struct iio_dev *iio_devs[ST_LSM6DSX_ID_MAX]; const struct st_lsm6dsx_settings *settings; + + struct iio_mount_matrix orientation; }; static __maybe_unused const struct iio_event_spec st_lsm6dsx_event = { @@ -477,4 +481,19 @@ st_lsm6dsx_write_locked(struct st_lsm6dsx_hw *hw, unsigned int addr, return err; } +static const inline struct iio_mount_matrix * +st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev, + const struct iio_chan_spec *chan) +{ + struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); + struct st_lsm6dsx_hw *hw = sensor->hw; + + return &hw->orientation; +} + +static const struct iio_chan_spec_ext_info st_lsm6dsx_accel_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_lsm6dsx_get_mount_matrix), + { } +}; + #endif /* ST_LSM6DSX_H */ diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index f3ad5694437a..345fdfc89ed1 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -2337,6 +2337,10 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, return err; } + err = iio_read_mount_matrix(hw->dev, "mount-matrix", &hw->orientation); + if (err) + return err; + for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { if (!hw->iio_devs[i]) continue; From 1bde330ca0e8173d9a735a8a0a590a6e87a366cf Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 12 Jan 2020 23:33:00 +0300 Subject: [PATCH 320/353] iio: accel: kxcjk1013: Support orientation matrix Hardware could be physically mounted in any possible direction and userpspace needs to be aware of the mounting orientation in order to process sensor's data correctly. In particular this helps iio-sensor-proxy to report display's orientation properly on a phone/tablet devices. Signed-off-by: Dmitry Osipenko Acked-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/accel/kxcjk-1013.c | 27 +++++++++++++++++++++++++-- include/linux/iio/accel/kxcjk_1013.h | 3 +++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index fee535d6e45b..c9924a65c32a 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -130,6 +130,7 @@ struct kxcjk1013_data { struct i2c_client *client; struct iio_trigger *dready_trig; struct iio_trigger *motion_trig; + struct iio_mount_matrix orientation; struct mutex mutex; s16 buffer[8]; u8 odr_bits; @@ -983,6 +984,20 @@ static const struct iio_event_spec kxcjk1013_event = { BIT(IIO_EV_INFO_PERIOD) }; +static const struct iio_mount_matrix * +kxcjk1013_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct kxcjk1013_data *data = iio_priv(indio_dev); + + return &data->orientation; +} + +static const struct iio_chan_spec_ext_info kxcjk1013_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, kxcjk1013_get_mount_matrix), + { } +}; + #define KXCJK1013_CHANNEL(_axis) { \ .type = IIO_ACCEL, \ .modified = 1, \ @@ -999,6 +1014,7 @@ static const struct iio_event_spec kxcjk1013_event = { .endianness = IIO_LE, \ }, \ .event_spec = &kxcjk1013_event, \ + .ext_info = kxcjk1013_ext_info, \ .num_event_specs = 1 \ } @@ -1267,11 +1283,18 @@ static int kxcjk1013_probe(struct i2c_client *client, data->client = client; pdata = dev_get_platdata(&client->dev); - if (pdata) + if (pdata) { data->active_high_intr = pdata->active_high_intr; - else + data->orientation = pdata->orientation; + } else { data->active_high_intr = true; /* default polarity */ + ret = iio_read_mount_matrix(&client->dev, "mount-matrix", + &data->orientation); + if (ret) + return ret; + } + if (id) { data->chipset = (enum kx_chipset)(id->driver_data); name = id->name; diff --git a/include/linux/iio/accel/kxcjk_1013.h b/include/linux/iio/accel/kxcjk_1013.h index 8c3c78bc9f91..ea0ecb774371 100644 --- a/include/linux/iio/accel/kxcjk_1013.h +++ b/include/linux/iio/accel/kxcjk_1013.h @@ -7,8 +7,11 @@ #ifndef __IIO_KXCJK_1013_H__ #define __IIO_KXCJK_1013_H__ +#include + struct kxcjk_1013_platform_data { bool active_high_intr; + struct iio_mount_matrix orientation; }; #endif From 0013ccaa136ddaa59c6fc2b2c8fbb3e865cdf8b1 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 12 Jan 2020 23:33:01 +0300 Subject: [PATCH 321/353] dt-bindings: iio: accel: kxcjk1013: Document mount-matrix property The generic IIO mount-matrix property conveys physical orientation of the hardware chip. Signed-off-by: Dmitry Osipenko Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/accel/kionix,kxcjk1013.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/accel/kionix,kxcjk1013.txt b/Documentation/devicetree/bindings/iio/accel/kionix,kxcjk1013.txt index eb76a02e2a82..ce950e162d5d 100644 --- a/Documentation/devicetree/bindings/iio/accel/kionix,kxcjk1013.txt +++ b/Documentation/devicetree/bindings/iio/accel/kionix,kxcjk1013.txt @@ -9,9 +9,16 @@ Required properties: "kionix,kxtf9" - reg: i2c slave address +Optional properties: + + - mount-matrix: an optional 3x3 mounting rotation matrix + Example: kxtf9@f { compatible = "kionix,kxtf9"; reg = <0x0F>; + mount-matrix = "0", "1", "0", + "1", "0", "0", + "0", "0", "1"; }; From 4a001c96b1c6d39831be3ef957968404be96d75e Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 13 Jan 2020 14:14:25 +0100 Subject: [PATCH 322/353] iio: dac: stm32-dac: use reset controller only at probe time This change removes the reset controller reference from the local DAC instance since it is used only at probe time. Signed-off-by: Etienne Carriere Signed-off-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/dac/stm32-dac-core.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c index 9e6b4cd0a5cc..4d93446c58f5 100644 --- a/drivers/iio/dac/stm32-dac-core.c +++ b/drivers/iio/dac/stm32-dac-core.c @@ -20,13 +20,11 @@ /** * struct stm32_dac_priv - stm32 DAC core private data * @pclk: peripheral clock common for all DACs - * @rst: peripheral reset control * @vref: regulator reference * @common: Common data for all DAC instances */ struct stm32_dac_priv { struct clk *pclk; - struct reset_control *rst; struct regulator *vref; struct stm32_dac_common common; }; @@ -94,6 +92,7 @@ static int stm32_dac_probe(struct platform_device *pdev) struct regmap *regmap; struct resource *res; void __iomem *mmio; + struct reset_control *rst; int ret; if (!dev->of_node) @@ -148,11 +147,11 @@ static int stm32_dac_probe(struct platform_device *pdev) priv->common.vref_mv = ret / 1000; dev_dbg(dev, "vref+=%dmV\n", priv->common.vref_mv); - priv->rst = devm_reset_control_get_exclusive(dev, NULL); - if (!IS_ERR(priv->rst)) { - reset_control_assert(priv->rst); + rst = devm_reset_control_get_exclusive(dev, NULL); + if (!IS_ERR(rst)) { + reset_control_assert(rst); udelay(2); - reset_control_deassert(priv->rst); + reset_control_deassert(rst); } if (cfg && cfg->has_hfsel) { From d344961f55fd6321937d3bc92ad3930dea31189f Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Mon, 13 Jan 2020 14:14:26 +0100 Subject: [PATCH 323/353] iio: dac: stm32-dac: better handle reset controller failures Use devm_reset_control_get_optional_exclusive() instead of devm_reset_control_get_exclusive() as reset controller is optional. Nevertheless if reset controller is expected but reports an error, propagate the error code to the caller. In such case a nice error trace is emitted unless we're deferring the probe operation. Signed-off-by: Etienne Carriere Signed-off-by: Fabrice Gasnier Signed-off-by: Jonathan Cameron --- drivers/iio/dac/stm32-dac-core.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c index 4d93446c58f5..7e5809ba0dee 100644 --- a/drivers/iio/dac/stm32-dac-core.c +++ b/drivers/iio/dac/stm32-dac-core.c @@ -147,8 +147,16 @@ static int stm32_dac_probe(struct platform_device *pdev) priv->common.vref_mv = ret / 1000; dev_dbg(dev, "vref+=%dmV\n", priv->common.vref_mv); - rst = devm_reset_control_get_exclusive(dev, NULL); - if (!IS_ERR(rst)) { + rst = devm_reset_control_get_optional_exclusive(dev, NULL); + if (rst) { + if (IS_ERR(rst)) { + ret = PTR_ERR(rst); + if (ret != -EPROBE_DEFER) + dev_err(dev, "reset get failed, %d\n", ret); + + goto err_hw_stop; + } + reset_control_assert(rst); udelay(2); reset_control_deassert(rst); From 27f391a5d628f860e2245f59f97461cbd22433f1 Mon Sep 17 00:00:00 2001 From: Felipe Cardoso Resende Date: Thu, 16 Jan 2020 21:42:14 -0300 Subject: [PATCH 324/353] Staging: kpc2000: Remove warning: "dubious: x | !y" detected by sparse Sparse complains about "dubious: x | !y". This patch adds some macros to make it clear if a flag will be enabled or not so Sparse stops complaining about dubious code construct. Signed-off-by: Felipe Cardoso Resende Link: https://lore.kernel.org/r/20200117004214.GA1800@felipe-pc Signed-off-by: Greg Kroah-Hartman --- drivers/staging/kpc2000/kpc2000_i2c.c | 78 +++++++++++++++------------ 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index 5460bf973c9c..10b9cee9bffd 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -572,6 +572,10 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, return 0; } +#define enable_flag(x) (x) +#define disable_flag(x) 0 +#define enable_flag_if(x, cond) ((cond) ? (x) : 0) + static u32 i801_func(struct i2c_adapter *adapter) { struct i2c_device *priv = i2c_get_adapdata(adapter); @@ -588,42 +592,42 @@ static u32 i801_func(struct i2c_adapter *adapter) // http://lxr.free-electrons.com/source/include/uapi/linux/i2c.h#L85 u32 f = - I2C_FUNC_I2C | /* 0x00000001(I enabled this - * one) - */ - !I2C_FUNC_10BIT_ADDR | /* 0x00000002 */ - !I2C_FUNC_PROTOCOL_MANGLING | /* 0x00000004 */ - ((priv->features & FEATURE_SMBUS_PEC) ? - I2C_FUNC_SMBUS_PEC : 0) | /* 0x00000008 */ - !I2C_FUNC_SMBUS_BLOCK_PROC_CALL | /* 0x00008000 */ - I2C_FUNC_SMBUS_QUICK | /* 0x00010000 */ - !I2C_FUNC_SMBUS_READ_BYTE | /* 0x00020000 */ - !I2C_FUNC_SMBUS_WRITE_BYTE | /* 0x00040000 */ - !I2C_FUNC_SMBUS_READ_BYTE_DATA | /* 0x00080000 */ - !I2C_FUNC_SMBUS_WRITE_BYTE_DATA | /* 0x00100000 */ - !I2C_FUNC_SMBUS_READ_WORD_DATA | /* 0x00200000 */ - !I2C_FUNC_SMBUS_WRITE_WORD_DATA | /* 0x00400000 */ - !I2C_FUNC_SMBUS_PROC_CALL | /* 0x00800000 */ - !I2C_FUNC_SMBUS_READ_BLOCK_DATA | /* 0x01000000 */ - !I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | /* 0x02000000 */ - ((priv->features & FEATURE_I2C_BLOCK_READ) ? - I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0) | /* 0x04000000 */ - I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | /* 0x08000000 */ + enable_flag(I2C_FUNC_I2C) | /* 0x00000001(I enabled this one) */ + disable_flag(I2C_FUNC_10BIT_ADDR) | /* 0x00000002 */ + disable_flag(I2C_FUNC_PROTOCOL_MANGLING) | /* 0x00000004 */ + enable_flag_if(I2C_FUNC_SMBUS_PEC, + priv->features & FEATURE_SMBUS_PEC) | + /* 0x00000008 */ + disable_flag(I2C_FUNC_SMBUS_BLOCK_PROC_CALL) | /* 0x00008000 */ + enable_flag(I2C_FUNC_SMBUS_QUICK) | /* 0x00010000 */ + disable_flag(I2C_FUNC_SMBUS_READ_BYTE) | /* 0x00020000 */ + disable_flag(I2C_FUNC_SMBUS_WRITE_BYTE) | /* 0x00040000 */ + disable_flag(I2C_FUNC_SMBUS_READ_BYTE_DATA) | /* 0x00080000 */ + disable_flag(I2C_FUNC_SMBUS_WRITE_BYTE_DATA) | /* 0x00100000 */ + disable_flag(I2C_FUNC_SMBUS_READ_WORD_DATA) | /* 0x00200000 */ + disable_flag(I2C_FUNC_SMBUS_WRITE_WORD_DATA) | /* 0x00400000 */ + disable_flag(I2C_FUNC_SMBUS_PROC_CALL) | /* 0x00800000 */ + disable_flag(I2C_FUNC_SMBUS_READ_BLOCK_DATA) | /* 0x01000000 */ + disable_flag(I2C_FUNC_SMBUS_WRITE_BLOCK_DATA) | /* 0x02000000 */ + enable_flag_if(I2C_FUNC_SMBUS_READ_I2C_BLOCK, + priv->features & FEATURE_I2C_BLOCK_READ) | + /* 0x04000000 */ + enable_flag(I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) | /* 0x08000000 */ - I2C_FUNC_SMBUS_BYTE | /* _READ_BYTE _WRITE_BYTE */ - I2C_FUNC_SMBUS_BYTE_DATA | /* _READ_BYTE_DATA - * _WRITE_BYTE_DATA - */ - I2C_FUNC_SMBUS_WORD_DATA | /* _READ_WORD_DATA - * _WRITE_WORD_DATA - */ - I2C_FUNC_SMBUS_BLOCK_DATA | /* _READ_BLOCK_DATA - * _WRITE_BLOCK_DATA - */ - !I2C_FUNC_SMBUS_I2C_BLOCK | /* _READ_I2C_BLOCK - * _WRITE_I2C_BLOCK - */ - !I2C_FUNC_SMBUS_EMUL; /* _QUICK _BYTE + enable_flag(I2C_FUNC_SMBUS_BYTE) | /* _READ_BYTE _WRITE_BYTE */ + enable_flag(I2C_FUNC_SMBUS_BYTE_DATA) | /* _READ_BYTE_DATA + * _WRITE_BYTE_DATA + */ + enable_flag(I2C_FUNC_SMBUS_WORD_DATA) | /* _READ_WORD_DATA + * _WRITE_WORD_DATA + */ + enable_flag(I2C_FUNC_SMBUS_BLOCK_DATA) | /* _READ_BLOCK_DATA + * _WRITE_BLOCK_DATA + */ + disable_flag(I2C_FUNC_SMBUS_I2C_BLOCK) | /* _READ_I2C_BLOCK + * _WRITE_I2C_BLOCK + */ + disable_flag(I2C_FUNC_SMBUS_EMUL); /* _QUICK _BYTE * _BYTE_DATA _WORD_DATA * _PROC_CALL * _WRITE_BLOCK_DATA @@ -632,6 +636,10 @@ static u32 i801_func(struct i2c_adapter *adapter) return f; } +#undef enable_flag +#undef disable_flag +#undef enable_flag_if + static const struct i2c_algorithm smbus_algorithm = { .smbus_xfer = i801_access, .functionality = i801_func, From 0b4d1d0da7e16f6faa572a8c7f865ff82e097819 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 18 Jan 2020 18:33:41 +0100 Subject: [PATCH 325/353] staging: rtl8188eu: remove else after break or return Remove unnecessary else after break or return to improve readability and clear checkpatch warnings. WARNING: else is not generally useful after a break or return Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200118173343.32405-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_efuse.c | 9 ++-- .../staging/rtl8188eu/core/rtw_ieee80211.c | 18 +++---- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 53 +++++++++---------- .../staging/rtl8188eu/core/rtw_wlan_util.c | 8 ++- drivers/staging/rtl8188eu/core/rtw_xmit.c | 4 +- drivers/staging/rtl8188eu/hal/odm.c | 7 +-- drivers/staging/rtl8188eu/hal/phy.c | 45 ++++++++-------- .../staging/rtl8188eu/os_dep/ioctl_linux.c | 6 +-- 8 files changed, 69 insertions(+), 81 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 0b86ae8338d9..c525682d0edf 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -497,8 +497,8 @@ static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, st if (!PgWriteSuccess) return false; - else - efuse_addr = Efuse_GetCurrentSize(pAdapter); + + efuse_addr = Efuse_GetCurrentSize(pAdapter); } else { efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1; } @@ -713,10 +713,9 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u if (ALL_WORDS_DISABLED(efuse_data)) { ret = false; break; - } else { - curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); - curPkt.word_en = efuse_data & 0x0F; } + curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); + curPkt.word_en = efuse_data & 0x0F; } else { cur_header = efuse_data; curPkt.offset = (cur_header >> 4) & 0x0F; diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 1344d369e05d..29f615443e8f 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -157,11 +157,10 @@ u8 *rtw_get_ie(u8 *pbuf, int index, uint *len, int limit) if (*p == index) { *len = *(p + 1); return p; - } else { - tmp = *(p + 1); - p += (tmp + 2); - i += (tmp + 2); } + tmp = *(p + 1); + p += (tmp + 2); + i += (tmp + 2); if (i >= limit) break; } @@ -295,10 +294,9 @@ unsigned char *rtw_get_wpa_ie(unsigned char *pie, uint *wpa_ie_len, int limit) goto check_next_ie; *wpa_ie_len = *(pbuf + 1); return pbuf; - } else { - *wpa_ie_len = 0; - return NULL; } + *wpa_ie_len = 0; + return NULL; check_next_ie: limit_new = limit - (pbuf - pie) - 2 - len; @@ -596,9 +594,8 @@ u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen) cnt += in_ie[cnt + 1] + 2; break; - } else { - cnt += in_ie[cnt + 1] + 2; /* goto next */ } + cnt += in_ie[cnt + 1] + 2; /* goto next */ } return wpsie_ptr; } @@ -642,9 +639,8 @@ u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_att if (len_attr) *len_attr = attr_len; break; - } else { - attr_ptr += attr_len; /* goto next */ } + attr_ptr += attr_len; /* goto next */ } return target_attr_ptr; } diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 16cb5b31a31d..36841d20c3c1 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -1865,6 +1865,7 @@ unsigned int send_beacon(struct adapter *padapter) int issue = 0; int poll = 0; unsigned long start = jiffies; + u32 passing_time; rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL); do { @@ -1883,15 +1884,14 @@ unsigned int send_beacon(struct adapter *padapter) DBG_88E("%s fail! %u ms\n", __func__, jiffies_to_msecs(jiffies - start)); return _FAIL; - } else { - u32 passing_time = jiffies_to_msecs(jiffies - start); - - if (passing_time > 100 || issue > 3) - DBG_88E("%s success, issue:%d, poll:%d, %u ms\n", - __func__, issue, poll, - jiffies_to_msecs(jiffies - start)); - return _SUCCESS; } + passing_time = jiffies_to_msecs(jiffies - start); + + if (passing_time > 100 || issue > 3) + DBG_88E("%s success, issue:%d, poll:%d, %u ms\n", + __func__, issue, poll, + jiffies_to_msecs(jiffies - start)); + return _SUCCESS; } /**************************************************************************** @@ -2864,10 +2864,9 @@ static unsigned int OnAuthClient(struct adapter *padapter, set_link_timer(pmlmeext, REAUTH_TO); return _SUCCESS; - } else { - /* open system */ - go2asoc = 1; } + /* open system */ + go2asoc = 1; } else if (seq == 4) { if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) go2asoc = 1; @@ -3453,14 +3452,13 @@ static unsigned int OnDeAuth(struct adapter *padapter, } return _SUCCESS; - } else -#endif - { - DBG_88E_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM\n", - reason, GetAddr3Ptr(pframe)); - - receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); } +#endif + DBG_88E_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM\n", + reason, GetAddr3Ptr(pframe)); + + receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); + pmlmepriv->LinkDetectInfo.bBusyTraffic = false; return _SUCCESS; } @@ -3507,14 +3505,13 @@ static unsigned int OnDisassoc(struct adapter *padapter, } return _SUCCESS; - } else -#endif - { - DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n", - reason, GetAddr3Ptr(pframe)); - - receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); } +#endif + DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n", + reason, GetAddr3Ptr(pframe)); + + receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); + pmlmepriv->LinkDetectInfo.bBusyTraffic = false; return _SUCCESS; } @@ -5277,10 +5274,10 @@ u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf) write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key); return H2C_SUCCESS_RSP; - } else { - DBG_88E("r871x_set_stakey_hdl(): sta has been free\n"); - return H2C_REJECTED; } + + DBG_88E("r871x_set_stakey_hdl(): sta has been free\n"); + return H2C_REJECTED; } /* below for sta mode */ diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index af8a79ce8736..6df873e4c2ed 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -1247,9 +1247,8 @@ unsigned char check_assoc_AP(u8 *pframe, uint len) if (ralink_vendor_flag) { DBG_88E("link to Tenda W311R AP\n"); return HT_IOT_PEER_TENDA; - } else { - DBG_88E("Capture EPIGRAM_OUI\n"); } + DBG_88E("Capture EPIGRAM_OUI\n"); } else { break; } @@ -1266,10 +1265,9 @@ unsigned char check_assoc_AP(u8 *pframe, uint len) } else if (ralink_vendor_flag && epigram_vendor_flag) { DBG_88E("link to Tenda W311R AP\n"); return HT_IOT_PEER_TENDA; - } else { - DBG_88E("link to new AP\n"); - return HT_IOT_PEER_UNKNOWN; } + DBG_88E("link to new AP\n"); + return HT_IOT_PEER_UNKNOWN; } void update_IOT_info(struct adapter *padapter) diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index c37591657bac..258531bc1408 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -1022,10 +1022,10 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct ClearMFrag(mem_start); break; - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: There're still something in packet!\n", __func__)); } + RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: There're still something in packet!\n", __func__)); + addr = (size_t)(pframe); mem_start = (unsigned char *)round_up(addr, 4) + hw_hdr_offset; diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 4e2f6cb55a75..7489491f5aaa 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -967,10 +967,11 @@ void ODM_TXPowerTrackingCheck(struct odm_dm_struct *pDM_Odm) pDM_Odm->RFCalibrateInfo.TM_Trigger = 1; return; - } else { - rtl88eu_dm_txpower_tracking_callback_thermalmeter(Adapter); - pDM_Odm->RFCalibrateInfo.TM_Trigger = 0; } + + rtl88eu_dm_txpower_tracking_callback_thermalmeter(Adapter); + pDM_Odm->RFCalibrateInfo.TM_Trigger = 0; + } /* 3============================================================ */ diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c index 51c40abfafaa..afaf9e55195a 100644 --- a/drivers/staging/rtl8188eu/hal/phy.c +++ b/drivers/staging/rtl8188eu/hal/phy.c @@ -923,27 +923,27 @@ static bool simularity_compare(struct adapter *adapt, s32 resulta[][8], } } return result; - } else { - if (!(sim_bitmap & 0x03)) { /* path A TX OK */ - for (i = 0; i < 2; i++) - resulta[3][i] = resulta[c1][i]; - } - if (!(sim_bitmap & 0x0c)) { /* path A RX OK */ - for (i = 2; i < 4; i++) - resulta[3][i] = resulta[c1][i]; - } - - if (!(sim_bitmap & 0x30)) { /* path B TX OK */ - for (i = 4; i < 6; i++) - resulta[3][i] = resulta[c1][i]; - } - - if (!(sim_bitmap & 0xc0)) { /* path B RX OK */ - for (i = 6; i < 8; i++) - resulta[3][i] = resulta[c1][i]; - } - return false; } + + if (!(sim_bitmap & 0x03)) { /* path A TX OK */ + for (i = 0; i < 2; i++) + resulta[3][i] = resulta[c1][i]; + } + if (!(sim_bitmap & 0x0c)) { /* path A RX OK */ + for (i = 2; i < 4; i++) + resulta[3][i] = resulta[c1][i]; + } + + if (!(sim_bitmap & 0x30)) { /* path B TX OK */ + for (i = 4; i < 6; i++) + resulta[3][i] = resulta[c1][i]; + } + + if (!(sim_bitmap & 0xc0)) { /* path B RX OK */ + for (i = 6; i < 8; i++) + resulta[3][i] = resulta[c1][i]; + } + return false; } static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8], @@ -1053,10 +1053,9 @@ static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8], result[t][3] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16; break; - } else { - ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, - ("Path A Rx IQK Fail!!\n")); } + ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, + ("Path A Rx IQK Fail!!\n")); } if (path_a_ok == 0x00) { diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index 47f4cc6a19a9..9b6ea86d1dcf 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -596,9 +596,8 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS); cnt += buf[cnt+1]+2; break; - } else { - cnt += buf[cnt+1]+2; /* goto next */ } + cnt += buf[cnt+1]+2; /* goto next */ } } } @@ -773,8 +772,7 @@ static int rtw_wx_set_pmkid(struct net_device *dev, DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n"); if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN)) return ret; - else - ret = true; + ret = true; blInserted = false; /* overwrite PMKID */ From 2dda0602859350b3868367601253d29eeccfd50a Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 18 Jan 2020 18:33:42 +0100 Subject: [PATCH 326/353] staging: rtl8188eu: remove redundant defines Remove redundant defines from hal8188e_phy_cfg.h and rtl8188e_dm.h. All of them are defined in odm.h with the same values. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200118173343.32405-2-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h | 5 ----- drivers/staging/rtl8188eu/include/rtl8188e_dm.h | 7 +------ 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h b/drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h index da66695a1d8f..0c5b2b0948f5 100644 --- a/drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h +++ b/drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h @@ -15,11 +15,6 @@ #define MAX_TXPWR_IDX_NMODE_92S 63 #define Reset_Cnt_Limit 3 -#define IQK_MAC_REG_NUM 4 -#define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM 9 -#define HP_THERMAL_NUM 8 - #define MAX_AGGR_NUM 0x07 diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h index 19204335ab4c..910b982ab775 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h @@ -10,12 +10,7 @@ enum{ UP_LINK, DOWN_LINK, }; -/* duplicate code,will move to ODM ######### */ -#define IQK_MAC_REG_NUM 4 -#define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM 9 -#define HP_THERMAL_NUM 8 -/* duplicate code,will move to ODM ######### */ + struct dm_priv { u8 DM_Type; u8 DMFlag; From 3cdab8823a50c208dbacaa8f1fb4a82ed2227ad9 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 18 Jan 2020 18:33:43 +0100 Subject: [PATCH 327/353] staging: rtl8188eu: remove unused enum and defines IQK_BB_REG_NUM_MAX, RTL8711_RF_MAX_SENS, RTL8711_RF_DEF_SENS, NUM_REGULATORYS and enum _RTL8712_RF_MIMO_CONFIG_ are not used in the driver code, remove them. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200118173343.32405-3-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/include/odm.h | 1 - drivers/staging/rtl8188eu/include/rtw_rf.h | 16 ---------------- 2 files changed, 17 deletions(-) diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h index 8245cea2feef..9d39fe13626a 100644 --- a/drivers/staging/rtl8188eu/include/odm.h +++ b/drivers/staging/rtl8188eu/include/odm.h @@ -239,7 +239,6 @@ struct odm_rate_adapt { #define IQK_MAC_REG_NUM 4 #define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM_MAX 10 #define IQK_BB_REG_NUM 9 #define HP_THERMAL_NUM 8 diff --git a/drivers/staging/rtl8188eu/include/rtw_rf.h b/drivers/staging/rtl8188eu/include/rtw_rf.h index b5dfb226f32a..c3847cf16ec1 100644 --- a/drivers/staging/rtl8188eu/include/rtw_rf.h +++ b/drivers/staging/rtl8188eu/include/rtw_rf.h @@ -19,9 +19,6 @@ #define SHORT_SLOT_TIME 9 #define NON_SHORT_SLOT_TIME 20 -#define RTL8711_RF_MAX_SENS 6 -#define RTL8711_RF_DEF_SENS 4 - /* We now define the following channels as the max channels in each * channel plan. */ @@ -30,8 +27,6 @@ #define MAX_CHANNEL_NUM_2G 14 #define MAX_CHANNEL_NUM 14 /* 2.4 GHz only */ -#define NUM_REGULATORYS 1 - /* Country codes */ #define USA 0x555320 #define EUROPE 0x1 /* temp, should be provided later */ @@ -74,17 +69,6 @@ enum _REG_PREAMBLE_MODE { PREAMBLE_SHORT = 3, }; -enum _RTL8712_RF_MIMO_CONFIG_ { - RTL8712_RFCONFIG_1T = 0x10, - RTL8712_RFCONFIG_2T = 0x20, - RTL8712_RFCONFIG_1R = 0x01, - RTL8712_RFCONFIG_2R = 0x02, - RTL8712_RFCONFIG_1T1R = 0x11, - RTL8712_RFCONFIG_1T2R = 0x12, - RTL8712_RFCONFIG_TURBO = 0x92, - RTL8712_RFCONFIG_2T2R = 0x22 -}; - enum rf90_radio_path { RF90_PATH_A = 0, /* Radio Path A */ RF90_PATH_B = 1, /* Radio Path B */ From 05ecd1038b0c06c4546e28fbe67732c3fa28ae10 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 18 Jan 2020 20:53:03 +0100 Subject: [PATCH 328/353] staging: rtl8192e: simplify rtl92e_evm_db_to_percent() Use clamp() to simplify function rtl92e_evm_db_to_percent() and reduce object file size. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200118195305.16685-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/rtl_core.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index dace81a7d1ba..caf36b6bf0dc 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -1973,18 +1973,11 @@ u8 rtl92e_rx_db_to_percent(s8 antpower) u8 rtl92e_evm_db_to_percent(s8 value) { - s8 ret_val; + s8 ret_val = clamp(-value, 0, 33) * 3; - ret_val = value; - - if (ret_val >= 0) - ret_val = 0; - if (ret_val <= -33) - ret_val = -33; - ret_val = 0 - ret_val; - ret_val *= 3; if (ret_val == 99) ret_val = 100; + return ret_val; } From 38c03040e24f7066cfa5b1718d07f0700ecb400b Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 18 Jan 2020 20:53:04 +0100 Subject: [PATCH 329/353] staging: rtl8192u: simplify rtl819x_evm_dbtopercentage() Use clamp() to simplify function rtl819x_evm_dbtopercentage() and reduce object file size. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200118195305.16685-2-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8192U_core.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 00fdcbf64b0b..a40ce0d7a467 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -3954,18 +3954,11 @@ static u8 rtl819x_query_rxpwrpercentage(s8 antpower) static u8 rtl819x_evm_dbtopercentage(s8 value) { - s8 ret_val; + s8 ret_val = clamp(-value, 0, 33) * 3; - ret_val = value; - - if (ret_val >= 0) - ret_val = 0; - if (ret_val <= -33) - ret_val = -33; - ret_val = 0 - ret_val; - ret_val *= 3; if (ret_val == 99) ret_val = 100; + return ret_val; } From 3063da91ca569ccafd6d07cd877d6d3588b2c85a Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sat, 18 Jan 2020 20:53:05 +0100 Subject: [PATCH 330/353] staging: rtl8712: simplify evm_db2percentage() Use clamp() to simplify function evm_db2percentage() and reduce object file size. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20200118195305.16685-3-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 00ea0beb12c9..116773943a2e 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -663,17 +663,11 @@ static u8 evm_db2percentage(s8 value) /* * -33dB~0dB to 0%~99% */ - s8 ret_val; + s8 ret_val = clamp(-value, 0, 33) * 3; - ret_val = value; - if (ret_val >= 0) - ret_val = 0; - if (ret_val <= -33) - ret_val = -33; - ret_val = -ret_val; - ret_val *= 3; if (ret_val == 99) ret_val = 100; + return ret_val; } From 4d1356ac12f4d5180d0df345d85ff0ee42b89c72 Mon Sep 17 00:00:00 2001 From: Andrey Shvetsov Date: Thu, 16 Jan 2020 18:22:39 +0100 Subject: [PATCH 331/353] staging: most: net: fix buffer overflow If the length of the socket buffer is 0xFFFFFFFF (max size for an unsigned int), then payload_len becomes 0xFFFFFFF1 after subtracting 14 (ETH_HLEN). Then, mdp_len is set to payload_len + 16 (MDP_HDR_LEN) which overflows and results in a value of 2. These values for payload_len and mdp_len will pass current buffer size checks. This patch checks if derived from skb->len sum may overflow. The check is based on the following idea: For any `unsigned V1, V2` and derived `unsigned SUM = V1 + V2`, `V1 + V2` overflows iif `SUM < V1`. Reported-by: Greg Kroah-Hartman Signed-off-by: Andrey Shvetsov Cc: stable Link: https://lore.kernel.org/r/20200116172238.6046-1-andrey.shvetsov@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/net/net.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index 8218c9a06cb5..5547e36e09de 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -82,6 +82,11 @@ static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) unsigned int payload_len = skb->len - ETH_HLEN; unsigned int mdp_len = payload_len + MDP_HDR_LEN; + if (mdp_len < skb->len) { + pr_err("drop: too large packet! (%u)\n", skb->len); + return -EINVAL; + } + if (mbo->buffer_length < mdp_len) { pr_err("drop: too small buffer! (%d for %d)\n", mbo->buffer_length, mdp_len); @@ -129,6 +134,11 @@ static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo) u8 *buff = mbo->virt_address; unsigned int mep_len = skb->len + MEP_HDR_LEN; + if (mep_len < skb->len) { + pr_err("drop: too large packet! (%u)\n", skb->len); + return -EINVAL; + } + if (mbo->buffer_length < mep_len) { pr_err("drop: too small buffer! (%d for %d)\n", mbo->buffer_length, mep_len); From 743b2b7e08c76d3090373e9cd354edef6a0822b7 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 19 Jan 2020 12:02:24 +0000 Subject: [PATCH 332/353] staging: vt6656: Simplify RX finding bit rates The bit rate can be found by multiplying the rate value by 5. Use rx_bitrate to compared to sband bitrates removing the need to find it by hw_value. Signed-off-by: Malcolm Priestley Link: https://lore.kernel.org/r/50d3c4b8-6d17-4fae-ce9c-88a50614450f@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 1 - drivers/staging/vt6656/dpc.c | 21 ++++++--------------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index e2fabe818b19..2f6567d92b83 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -264,7 +264,6 @@ struct vnt_private { struct usb_interface *intf; u64 tsf_time; - u8 rx_rate; u32 rx_buf_sz; int mc_list_count; diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 2bcb29b11883..a55e2f6b09e3 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -35,14 +35,13 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, u8 *rsr, *new_rsr, *rssi; __le64 *tsf_time; u32 frame_size; - int ii, r; - u8 *rx_rate, *sq, *sq_3; + int ii; + u8 *sq, *sq_3; u32 wbk_status; u8 *skb_data; u16 *pay_load_len; - u16 pay_load_with_padding; + u16 rx_bitrate, pay_load_with_padding; u8 rate_idx = 0; - u8 rate[MAX_RATE] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; long rx_dbm; skb = ptr_rcb->skb; @@ -66,8 +65,6 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, skb_data = (u8 *)skb->data; - rx_rate = skb_data + 5; - /* real Frame Size = USBframe_size -4WbkStatus - 4RxStatus */ /* -8TSF - 4RSR - 4SQ3 - ?Padding */ @@ -85,23 +82,17 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, } sband = hw->wiphy->bands[hw->conf.chandef.chan->band]; - - for (r = RATE_1M; r < MAX_RATE; r++) { - if (*rx_rate == rate[r]) - break; - } - - priv->rx_rate = r; + rx_bitrate = *(skb_data + 5) * 5; /* rx_rate * 5 */ for (ii = 0; ii < sband->n_bitrates; ii++) { - if (sband->bitrates[ii].hw_value == r) { + if (sband->bitrates[ii].bitrate == rx_bitrate) { rate_idx = ii; break; } } if (ii == sband->n_bitrates) { - dev_dbg(&priv->usb->dev, "Wrong RxRate %x\n", *rx_rate); + dev_dbg(&priv->usb->dev, "Wrong Rx Bit Rate %d\n", rx_bitrate); return false; } From 8902ecd70b3e3f13370af9f9e0134ad16e46fb50 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 19 Jan 2020 12:02:56 +0000 Subject: [PATCH 333/353] staging: vt6656: create vnt rx header for sk_buff. vnt_rx_header contains the structure of the original variables wbk_status, rx_sts, rx_rate and pay_load_len packed. Replace all the old variables for the ones in this. Signed-off-by: Malcolm Priestley Link: https://lore.kernel.org/r/094ee227-b114-ee75-67f7-bf07f8de099f@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 7 +++++++ drivers/staging/vt6656/dpc.c | 29 ++++++++++++----------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 2f6567d92b83..84d170420c8a 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -206,6 +206,13 @@ enum { CONTEXT_BEACON_PACKET }; +struct vnt_rx_header { + u32 wbk_status; + u8 rx_sts; + u8 rx_rate; + u16 pay_load_len; +} __packed; + /* RCB (Receive Control Block) */ struct vnt_rcb { void *priv; diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index a55e2f6b09e3..8fbb911144c6 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -31,15 +31,14 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, struct sk_buff *skb; struct ieee80211_rx_status *rx_status; struct ieee80211_hdr *hdr; + struct vnt_rx_header *head; __le16 fc; u8 *rsr, *new_rsr, *rssi; __le64 *tsf_time; u32 frame_size; int ii; u8 *sq, *sq_3; - u32 wbk_status; u8 *skb_data; - u16 *pay_load_len; u16 rx_bitrate, pay_load_with_padding; u8 rate_idx = 0; long rx_dbm; @@ -48,8 +47,8 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, rx_status = IEEE80211_SKB_RXCB(skb); /* [31:16]RcvByteCount ( not include 4-byte Status ) */ - wbk_status = *((u32 *)(skb->data)); - frame_size = wbk_status >> 16; + head = (struct vnt_rx_header *)skb->data; + frame_size = head->wbk_status >> 16; frame_size += 4; if (bytes_received != frame_size) { @@ -70,19 +69,17 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, /* if SQ3 the range is 24~27, if no SQ3 the range is 20~23 */ - pay_load_len = (u16 *)(skb_data + 6); - /*Fix hardware bug => PLCP_Length error */ - if (((bytes_received - (*pay_load_len)) > 27) || - ((bytes_received - (*pay_load_len)) < 24) || - (bytes_received < (*pay_load_len))) { + if (((bytes_received - head->pay_load_len) > 27) || + ((bytes_received - head->pay_load_len) < 24) || + (bytes_received < head->pay_load_len)) { dev_dbg(&priv->usb->dev, "Wrong PLCP Length %x\n", - *pay_load_len); + head->pay_load_len); return false; } sband = hw->wiphy->bands[hw->conf.chandef.chan->band]; - rx_bitrate = *(skb_data + 5) * 5; /* rx_rate * 5 */ + rx_bitrate = head->rx_rate * 5; /* rx_rate * 5 */ for (ii = 0; ii < sband->n_bitrates; ii++) { if (sband->bitrates[ii].bitrate == rx_bitrate) { @@ -96,8 +93,8 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, return false; } - pay_load_with_padding = ((*pay_load_len / 4) + - ((*pay_load_len % 4) ? 1 : 0)) * 4; + pay_load_with_padding = ((head->pay_load_len / 4) + + ((head->pay_load_len % 4) ? 1 : 0)) * 4; tsf_time = (__le64 *)(skb_data + 8 + pay_load_with_padding); @@ -118,15 +115,13 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, if (*rsr & (RSR_IVLDTYP | RSR_IVLDLEN)) return false; - frame_size = *pay_load_len; - vnt_rf_rssi_to_dbm(priv, *rssi, &rx_dbm); priv->bb_pre_ed_rssi = (u8)rx_dbm + 1; priv->current_rssi = priv->bb_pre_ed_rssi; - skb_pull(skb, 8); - skb_trim(skb, frame_size); + skb_pull(skb, sizeof(*head)); + skb_trim(skb, head->pay_load_len); rx_status->mactime = priv->tsf_time; rx_status->band = hw->conf.chandef.chan->band; From b653174327e989cbc97f545ce33d30e1fe9de532 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 19 Jan 2020 12:03:41 +0000 Subject: [PATCH 334/353] staging: vt6656: Use vnt_rx_tail struct for tail variables. Place tsf_time, sq, new_rsr, rssi, rsr and sq3 packed in the structure. Unused variables are removed along with skb_data and structure is placed beyond vnt_rx_header + pay_load_with_padding on skb->data. Signed-off-by: Malcolm Priestley Link: https://lore.kernel.org/r/6ac6eae0-7b71-fefe-9230-da3b345b634b@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 9 +++++++++ drivers/staging/vt6656/dpc.c | 33 ++++++++------------------------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 84d170420c8a..fe6c11266123 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -213,6 +213,15 @@ struct vnt_rx_header { u16 pay_load_len; } __packed; +struct vnt_rx_tail { + __le64 tsf_time; + u8 sq; + u8 new_rsr; + u8 rssi; + u8 rsr; + u8 sq_3; +} __packed; + /* RCB (Receive Control Block) */ struct vnt_rcb { void *priv; diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 8fbb911144c6..981de5687341 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -32,13 +32,10 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, struct ieee80211_rx_status *rx_status; struct ieee80211_hdr *hdr; struct vnt_rx_header *head; + struct vnt_rx_tail *tail; __le16 fc; - u8 *rsr, *new_rsr, *rssi; - __le64 *tsf_time; u32 frame_size; int ii; - u8 *sq, *sq_3; - u8 *skb_data; u16 rx_bitrate, pay_load_with_padding; u8 rate_idx = 0; long rx_dbm; @@ -62,8 +59,6 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, return false; } - skb_data = (u8 *)skb->data; - /* real Frame Size = USBframe_size -4WbkStatus - 4RxStatus */ /* -8TSF - 4RSR - 4SQ3 - ?Padding */ @@ -96,26 +91,14 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, pay_load_with_padding = ((head->pay_load_len / 4) + ((head->pay_load_len % 4) ? 1 : 0)) * 4; - tsf_time = (__le64 *)(skb_data + 8 + pay_load_with_padding); + tail = (struct vnt_rx_tail *)(skb->data + + sizeof(*head) + pay_load_with_padding); + priv->tsf_time = le64_to_cpu(tail->tsf_time); - priv->tsf_time = le64_to_cpu(*tsf_time); - - if (priv->bb_type == BB_TYPE_11G) { - sq_3 = skb_data + 8 + pay_load_with_padding + 12; - sq = sq_3; - } else { - sq = skb_data + 8 + pay_load_with_padding + 8; - sq_3 = sq; - } - - new_rsr = skb_data + 8 + pay_load_with_padding + 9; - rssi = skb_data + 8 + pay_load_with_padding + 10; - - rsr = skb_data + 8 + pay_load_with_padding + 11; - if (*rsr & (RSR_IVLDTYP | RSR_IVLDLEN)) + if (tail->rsr & (RSR_IVLDTYP | RSR_IVLDLEN)) return false; - vnt_rf_rssi_to_dbm(priv, *rssi, &rx_dbm); + vnt_rf_rssi_to_dbm(priv, tail->rssi, &rx_dbm); priv->bb_pre_ed_rssi = (u8)rx_dbm + 1; priv->current_rssi = priv->bb_pre_ed_rssi; @@ -129,7 +112,7 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, rx_status->flag = 0; rx_status->freq = hw->conf.chandef.chan->center_freq; - if (!(*rsr & RSR_CRCOK)) + if (!(tail->rsr & RSR_CRCOK)) rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; hdr = (struct ieee80211_hdr *)(skb->data); @@ -142,7 +125,7 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, rx_status->flag |= RX_FLAG_DECRYPTED; /* Drop packet */ - if (!(*new_rsr & NEWRSR_DECRYPTOK)) { + if (!(tail->new_rsr & NEWRSR_DECRYPTOK)) { dev_kfree_skb(skb); return true; } From 1ca9c731057994e5b1f98e9869127af61f3c0cd3 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 19 Jan 2020 12:04:05 +0000 Subject: [PATCH 335/353] staging: vt6656: Just check NEWRSR_DECRYPTOK for RX_FLAG_DECRYPTED. At present the driver does a number of checks for RX_FLAG_DECRYPTED. Remove all these and just pass check NEWRSR_DECRYPTOK mac80211 will handle the processing of the sk_buff and dispose of it. This means that mac80211 can do unsupported encryption modes on stack. Signed-off-by: Malcolm Priestley Link: https://lore.kernel.org/r/75bbaa08-2465-b057-64ce-b67933409bc6@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/dpc.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 981de5687341..821aae8ca402 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -30,10 +30,8 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, struct ieee80211_supported_band *sband; struct sk_buff *skb; struct ieee80211_rx_status *rx_status; - struct ieee80211_hdr *hdr; struct vnt_rx_header *head; struct vnt_rx_tail *tail; - __le16 fc; u32 frame_size; int ii; u16 rx_bitrate, pay_load_with_padding; @@ -115,22 +113,10 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb, if (!(tail->rsr & RSR_CRCOK)) rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - hdr = (struct ieee80211_hdr *)(skb->data); - fc = hdr->frame_control; - rx_status->rate_idx = rate_idx; - if (ieee80211_has_protected(fc)) { - if (priv->local_id > REV_ID_VT3253_A1) { - rx_status->flag |= RX_FLAG_DECRYPTED; - - /* Drop packet */ - if (!(tail->new_rsr & NEWRSR_DECRYPTOK)) { - dev_kfree_skb(skb); - return true; - } - } - } + if (tail->new_rsr & NEWRSR_DECRYPTOK) + rx_status->flag |= RX_FLAG_DECRYPTED; ieee80211_rx_irqsafe(priv->hw, skb); From 747a64bd01f869f8b987e17992bba1db8108161a Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 19 Jan 2020 12:04:34 +0000 Subject: [PATCH 336/353] staging: vt6656: Remove memory buffer from vnt_download_firmware. The memory buffer is being done twice here as vnt_control_out passes it straight to kmemdup. Remove buffer and add const to the variable in vnt_control_out to pass the pointer to it. Signed-off-by: Malcolm Priestley Link: https://lore.kernel.org/r/be025ed0-204d-e957-4bc9-963e841fcb2c@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/firmware.c | 14 ++------------ drivers/staging/vt6656/usbpipe.c | 2 +- drivers/staging/vt6656/usbpipe.h | 2 +- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c index 60a00af250bf..70358d427211 100644 --- a/drivers/staging/vt6656/firmware.c +++ b/drivers/staging/vt6656/firmware.c @@ -30,7 +30,6 @@ int vnt_download_firmware(struct vnt_private *priv) { struct device *dev = &priv->usb->dev; const struct firmware *fw; - void *buffer = NULL; u16 length; int ii; int ret = 0; @@ -44,26 +43,17 @@ int vnt_download_firmware(struct vnt_private *priv) goto end; } - buffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL); - if (!buffer) { - ret = -ENOMEM; - goto free_fw; - } - for (ii = 0; ii < fw->size; ii += FIRMWARE_CHUNK_SIZE) { length = min_t(int, fw->size - ii, FIRMWARE_CHUNK_SIZE); - memcpy(buffer, fw->data + ii, length); ret = vnt_control_out(priv, 0, 0x1200 + ii, 0x0000, length, - buffer); + fw->data + ii); if (ret) - goto free_buffer; + goto free_fw; dev_dbg(dev, "Download firmware...%d %zu\n", ii, fw->size); } -free_buffer: - kfree(buffer); free_fw: release_firmware(fw); end: diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index d977d4777e4f..7bfccc48a366 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -34,7 +34,7 @@ #define USB_CTL_WAIT 500 /* ms */ int vnt_control_out(struct vnt_private *priv, u8 request, u16 value, - u16 index, u16 length, u8 *buffer) + u16 index, u16 length, const u8 *buffer) { int ret = 0; u8 *usb_buffer; diff --git a/drivers/staging/vt6656/usbpipe.h b/drivers/staging/vt6656/usbpipe.h index b65d9c01a211..4e3341bc3221 100644 --- a/drivers/staging/vt6656/usbpipe.h +++ b/drivers/staging/vt6656/usbpipe.h @@ -21,7 +21,7 @@ #define VNT_REG_BLOCK_SIZE 64 int vnt_control_out(struct vnt_private *priv, u8 request, u16 value, - u16 index, u16 length, u8 *buffer); + u16 index, u16 length, const u8 *buffer); int vnt_control_in(struct vnt_private *priv, u8 request, u16 value, u16 index, u16 length, u8 *buffer); From b5909c6d16fd4e3972b0cd48dedde08d55575342 Mon Sep 17 00:00:00 2001 From: Jerry Lin Date: Tue, 21 Jan 2020 10:46:21 +0800 Subject: [PATCH 337/353] staging: kpc2000: rename variables with kpc namespace Some namings in kpc2000_i2c are too ambiguous that may causing confusion to the readers. Rename some variable, function and struct name to prefix with 'kpc_i2c' to eliminate confusions. Signed-off-by: Jerry Lin Link: https://lore.kernel.org/r/20200121024620.GA10842@compute1 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/kpc2000/kpc2000_i2c.c | 40 +++++++++++++-------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index 10b9cee9bffd..07945f540428 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -32,7 +32,7 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Matt.Sickler@Daktronics.com"); -struct i2c_device { +struct kpc_i2c { unsigned long smba; struct i2c_adapter adapter; unsigned int features; @@ -131,7 +131,7 @@ struct i2c_device { /* Make sure the SMBus host is ready to start transmitting. * Return 0 if it is, -EBUSY if it is not. */ -static int i801_check_pre(struct i2c_device *priv) +static int i801_check_pre(struct kpc_i2c *priv) { int status; @@ -156,7 +156,7 @@ static int i801_check_pre(struct i2c_device *priv) } /* Convert the status register to an error code, and clear it. */ -static int i801_check_post(struct i2c_device *priv, int status, int timeout) +static int i801_check_post(struct kpc_i2c *priv, int status, int timeout) { int result = 0; @@ -206,7 +206,7 @@ static int i801_check_post(struct i2c_device *priv, int status, int timeout) return result; } -static int i801_transaction(struct i2c_device *priv, int xact) +static int i801_transaction(struct kpc_i2c *priv, int xact) { int status; int result; @@ -235,7 +235,7 @@ static int i801_transaction(struct i2c_device *priv, int xact) } /* wait for INTR bit as advised by Intel */ -static void i801_wait_hwpec(struct i2c_device *priv) +static void i801_wait_hwpec(struct kpc_i2c *priv) { int timeout = 0; int status; @@ -251,7 +251,7 @@ static void i801_wait_hwpec(struct i2c_device *priv) outb_p(status, SMBHSTSTS(priv)); } -static int i801_block_transaction_by_block(struct i2c_device *priv, +static int i801_block_transaction_by_block(struct kpc_i2c *priv, union i2c_smbus_data *data, char read_write, int hwpec) { @@ -285,7 +285,7 @@ static int i801_block_transaction_by_block(struct i2c_device *priv, return 0; } -static int i801_block_transaction_byte_by_byte(struct i2c_device *priv, +static int i801_block_transaction_byte_by_byte(struct kpc_i2c *priv, union i2c_smbus_data *data, char read_write, int command, int hwpec) @@ -367,7 +367,7 @@ static int i801_block_transaction_byte_by_byte(struct i2c_device *priv, return 0; } -static int i801_set_block_buffer_mode(struct i2c_device *priv) +static int i801_set_block_buffer_mode(struct kpc_i2c *priv) { outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv)); if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0) @@ -376,7 +376,7 @@ static int i801_set_block_buffer_mode(struct i2c_device *priv) } /* Block transaction function */ -static int i801_block_transaction(struct i2c_device *priv, +static int i801_block_transaction(struct kpc_i2c *priv, union i2c_smbus_data *data, char read_write, int command, int hwpec) { @@ -440,7 +440,7 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, int hwpec; int block = 0; int ret, xact = 0; - struct i2c_device *priv = i2c_get_adapdata(adap); + struct kpc_i2c *priv = i2c_get_adapdata(adap); hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC) && @@ -578,7 +578,7 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, static u32 i801_func(struct i2c_adapter *adapter) { - struct i2c_device *priv = i2c_get_adapdata(adapter); + struct kpc_i2c *priv = i2c_get_adapdata(adapter); /* original settings * u32 f = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | @@ -648,10 +648,10 @@ static const struct i2c_algorithm smbus_algorithm = { /******************************** *** Part 2 - Driver Handlers *** ********************************/ -static int pi2c_probe(struct platform_device *pldev) +static int kpc_i2c_probe(struct platform_device *pldev) { int err; - struct i2c_device *priv; + struct kpc_i2c *priv; struct resource *res; priv = devm_kzalloc(&pldev->dev, sizeof(*priv), GFP_KERNEL); @@ -700,11 +700,11 @@ static int pi2c_probe(struct platform_device *pldev) return 0; } -static int pi2c_remove(struct platform_device *pldev) +static int kpc_i2c_remove(struct platform_device *pldev) { - struct i2c_device *lddev; + struct kpc_i2c *lddev; - lddev = (struct i2c_device *)platform_get_drvdata(pldev); + lddev = (struct kpc_i2c *)platform_get_drvdata(pldev); i2c_del_adapter(&lddev->adapter); @@ -718,12 +718,12 @@ static int pi2c_remove(struct platform_device *pldev) return 0; } -static struct platform_driver i2c_plat_driver_i = { - .probe = pi2c_probe, - .remove = pi2c_remove, +static struct platform_driver kpc_i2c_driver = { + .probe = kpc_i2c_probe, + .remove = kpc_i2c_remove, .driver = { .name = KP_DRIVER_NAME_I2C, }, }; -module_platform_driver(i2c_plat_driver_i); +module_platform_driver(kpc_i2c_driver); From 9d442d2b9add140ddc2c5de6a0ac93050dfaef16 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Fri, 17 Jan 2020 10:31:23 +0000 Subject: [PATCH 338/353] staging: wilc1000: remove use of infinite loop conditions Avoid the use of 'while (1)' infinite loop conditions. It's not recommended to have infinite loop in kernel code because a small bug can cause never ending loops so use terminator condition as suggested in full driver review [1]. [1]. https://lore.kernel.org/linux-wireless/20191023100313.52B3F606CF@smtp.codeaurora.org/ Signed-off-by: Ajay Singh Link: https://lore.kernel.org/r/20200117160157.8706-2-ajay.kathat@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/netdev.c | 7 +- drivers/staging/wilc1000/wlan.c | 81 ++++++--------- drivers/staging/wilc1000/wlan_cfg.c | 152 ++++++++++------------------ 3 files changed, 89 insertions(+), 151 deletions(-) diff --git a/drivers/staging/wilc1000/netdev.c b/drivers/staging/wilc1000/netdev.c index 3fd8e008f733..960dbc8d5173 100644 --- a/drivers/staging/wilc1000/netdev.c +++ b/drivers/staging/wilc1000/netdev.c @@ -837,7 +837,7 @@ static const struct net_device_ops wilc_netdev_ops = { void wilc_netdev_cleanup(struct wilc *wilc) { struct wilc_vif *vif; - int srcu_idx; + int srcu_idx, ifc_cnt = 0; if (!wilc) return; @@ -858,7 +858,7 @@ void wilc_netdev_cleanup(struct wilc *wilc) flush_workqueue(wilc->hif_workqueue); destroy_workqueue(wilc->hif_workqueue); - do { + while (ifc_cnt < WILC_NUM_CONCURRENT_IFC) { mutex_lock(&wilc->vif_mutex); if (wilc->vif_num <= 0) { mutex_unlock(&wilc->vif_mutex); @@ -871,7 +871,8 @@ void wilc_netdev_cleanup(struct wilc *wilc) wilc->vif_num--; mutex_unlock(&wilc->vif_mutex); synchronize_srcu(&wilc->srcu); - } while (1); + ifc_cnt++; + } wilc_wlan_cfg_deinit(wilc); wlan_deinit_locks(wilc); diff --git a/drivers/staging/wilc1000/wlan.c b/drivers/staging/wilc1000/wlan.c index ba5446724c93..c32af7076012 100644 --- a/drivers/staging/wilc1000/wlan.c +++ b/drivers/staging/wilc1000/wlan.c @@ -499,37 +499,31 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) wilc_wlan_txq_filter_dup_tcp_ack(dev); i = 0; sum = 0; - do { - if (tqe && (i < (WILC_VMM_TBL_SIZE - 1))) { - if (tqe->type == WILC_CFG_PKT) - vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET; + while (tqe && (i < (WILC_VMM_TBL_SIZE - 1))) { + if (tqe->type == WILC_CFG_PKT) + vmm_sz = ETH_CONFIG_PKT_HDR_OFFSET; + else if (tqe->type == WILC_NET_PKT) + vmm_sz = ETH_ETHERNET_HDR_OFFSET; + else + vmm_sz = HOST_HDR_OFFSET; - else if (tqe->type == WILC_NET_PKT) - vmm_sz = ETH_ETHERNET_HDR_OFFSET; + vmm_sz += tqe->buffer_size; - else - vmm_sz = HOST_HDR_OFFSET; + if (vmm_sz & 0x3) + vmm_sz = (vmm_sz + 4) & ~0x3; - vmm_sz += tqe->buffer_size; - - if (vmm_sz & 0x3) - vmm_sz = (vmm_sz + 4) & ~0x3; - - if ((sum + vmm_sz) > WILC_TX_BUFF_SIZE) - break; - - vmm_table[i] = vmm_sz / 4; - if (tqe->type == WILC_CFG_PKT) - vmm_table[i] |= BIT(10); - cpu_to_le32s(&vmm_table[i]); - - i++; - sum += vmm_sz; - tqe = wilc_wlan_txq_get_next(wilc, tqe); - } else { + if ((sum + vmm_sz) > WILC_TX_BUFF_SIZE) break; - } - } while (1); + + vmm_table[i] = vmm_sz / 4; + if (tqe->type == WILC_CFG_PKT) + vmm_table[i] |= BIT(10); + cpu_to_le32s(&vmm_table[i]); + + i++; + sum += vmm_sz; + tqe = wilc_wlan_txq_get_next(wilc, tqe); + } if (i == 0) goto out; @@ -594,12 +588,8 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) break; reg &= ~BIT(0); ret = func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, reg); - if (!ret) - break; - break; } - break; - } while (1); + } while (0); if (!ret) goto out_release_bus; @@ -725,9 +715,7 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size) } } offset += tp_len; - if (offset >= size) - break; - } while (1); + } while (offset < size); } static void wilc_wlan_handle_rxq(struct wilc *wilc) @@ -736,11 +724,7 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) u8 *buffer; struct rxq_entry_t *rqe; - do { - if (wilc->quit) { - complete(&wilc->cfg_event); - break; - } + while (!wilc->quit) { rqe = wilc_wlan_rxq_remove(wilc); if (!rqe) break; @@ -750,7 +734,9 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) wilc_wlan_handle_rx_buff(wilc, buffer, size); kfree(rqe); - } while (1); + } + if (wilc->quit) + complete(&wilc->cfg_event); } static void wilc_unknown_isr_ext(struct wilc *wilc) @@ -969,21 +955,14 @@ void wilc_wlan_cleanup(struct net_device *dev) struct wilc *wilc = vif->wilc; wilc->quit = 1; - do { - tqe = wilc_wlan_txq_remove_from_head(dev); - if (!tqe) - break; + while ((tqe = wilc_wlan_txq_remove_from_head(dev))) { if (tqe->tx_complete_func) tqe->tx_complete_func(tqe->priv, 0); kfree(tqe); - } while (1); + } - do { - rqe = wilc_wlan_rxq_remove(wilc); - if (!rqe) - break; + while ((rqe = wilc_wlan_rxq_remove(wilc))) kfree(rqe); - } while (1); kfree(wilc->rx_buffer); wilc->rx_buffer = NULL; diff --git a/drivers/staging/wilc1000/wlan_cfg.c b/drivers/staging/wilc1000/wlan_cfg.c index 2538435b82fd..fe2a7ed8e5cd 100644 --- a/drivers/staging/wilc1000/wlan_cfg.c +++ b/drivers/staging/wilc1000/wlan_cfg.c @@ -137,6 +137,7 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size) { u16 wid; u32 len = 0, i = 0; + struct wilc_cfg *cfg = &wl->cfg; while (size > 0) { i = 0; @@ -144,63 +145,42 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size) switch (FIELD_GET(WILC_WID_TYPE, wid)) { case WID_CHAR: - do { - if (wl->cfg.b[i].id == WID_NIL) - break; - - if (wl->cfg.b[i].id == wid) { - wl->cfg.b[i].val = info[4]; - break; - } + while (cfg->b[i].id != WID_NIL && cfg->b[i].id != wid) i++; - } while (1); + + if (cfg->b[i].id == wid) + cfg->b[i].val = info[4]; + len = 3; break; case WID_SHORT: - do { - struct wilc_cfg_hword *hw = &wl->cfg.hw[i]; - - if (hw->id == WID_NIL) - break; - - if (hw->id == wid) { - hw->val = get_unaligned_le16(&info[4]); - break; - } + while (cfg->hw[i].id != WID_NIL && cfg->hw[i].id != wid) i++; - } while (1); + + if (cfg->hw[i].id == wid) + cfg->hw[i].val = get_unaligned_le16(&info[4]); + len = 4; break; case WID_INT: - do { - struct wilc_cfg_word *w = &wl->cfg.w[i]; - - if (w->id == WID_NIL) - break; - - if (w->id == wid) { - w->val = get_unaligned_le32(&info[4]); - break; - } + while (cfg->w[i].id != WID_NIL && cfg->w[i].id != wid) i++; - } while (1); + + if (cfg->w[i].id == wid) + cfg->w[i].val = get_unaligned_le32(&info[4]); + len = 6; break; case WID_STR: - do { - if (wl->cfg.s[i].id == WID_NIL) - break; - - if (wl->cfg.s[i].id == wid) { - memcpy(wl->cfg.s[i].str, &info[2], - (info[2] + 2)); - break; - } + while (cfg->s[i].id != WID_NIL && cfg->s[i].id != wid) i++; - } while (1); + + if (cfg->s[i].id == wid) + memcpy(cfg->s[i].str, &info[2], info[2] + 2); + len = 2 + info[2]; break; @@ -223,16 +203,12 @@ static void wilc_wlan_parse_info_frame(struct wilc *wl, u8 *info) if (len == 1 && wid == WID_STATUS) { int i = 0; - do { - if (wl->cfg.b[i].id == WID_NIL) - break; - - if (wl->cfg.b[i].id == wid) { - wl->cfg.b[i].val = info[3]; - break; - } + while (wl->cfg.b[i].id != WID_NIL && + wl->cfg.b[i].id != wid) i++; - } while (1); + + if (wl->cfg.b[i].id == wid) + wl->cfg.b[i].val = info[3]; } } @@ -292,63 +268,45 @@ int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, { u8 type = FIELD_GET(WILC_WID_TYPE, wid); int i, ret = 0; + struct wilc_cfg *cfg = &wl->cfg; i = 0; if (type == CFG_BYTE_CMD) { - do { - if (wl->cfg.b[i].id == WID_NIL) - break; - - if (wl->cfg.b[i].id == wid) { - memcpy(buffer, &wl->cfg.b[i].val, 1); - ret = 1; - break; - } + while (cfg->b[i].id != WID_NIL && cfg->b[i].id != wid) i++; - } while (1); + + if (cfg->b[i].id == wid) { + memcpy(buffer, &cfg->b[i].val, 1); + ret = 1; + } } else if (type == CFG_HWORD_CMD) { - do { - if (wl->cfg.hw[i].id == WID_NIL) - break; - - if (wl->cfg.hw[i].id == wid) { - memcpy(buffer, &wl->cfg.hw[i].val, 2); - ret = 2; - break; - } + while (cfg->hw[i].id != WID_NIL && cfg->hw[i].id != wid) i++; - } while (1); + + if (cfg->hw[i].id == wid) { + memcpy(buffer, &cfg->hw[i].val, 2); + ret = 2; + } } else if (type == CFG_WORD_CMD) { - do { - if (wl->cfg.w[i].id == WID_NIL) - break; - - if (wl->cfg.w[i].id == wid) { - memcpy(buffer, &wl->cfg.w[i].val, 4); - ret = 4; - break; - } + while (cfg->w[i].id != WID_NIL && cfg->w[i].id != wid) i++; - } while (1); + + if (cfg->w[i].id == wid) { + memcpy(buffer, &cfg->w[i].val, 4); + ret = 4; + } } else if (type == CFG_STR_CMD) { - do { - u32 id = wl->cfg.s[i].id; - - if (id == WID_NIL) - break; - - if (id == wid) { - u16 size = get_unaligned_le16(wl->cfg.s[i].str); - - if (buffer_size >= size) { - memcpy(buffer, &wl->cfg.s[i].str[2], - size); - ret = size; - } - break; - } + while (cfg->s[i].id != WID_NIL && cfg->s[i].id != wid) i++; - } while (1); + + if (cfg->s[i].id == wid) { + u16 size = get_unaligned_le16(cfg->s[i].str); + + if (buffer_size >= size) { + memcpy(buffer, &cfg->s[i].str[2], size); + ret = size; + } + } } return ret; } From c5295d1a41fe2f1bd0877f74817a3b63b989b10e Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Fri, 17 Jan 2020 10:31:25 +0000 Subject: [PATCH 339/353] staging: wilc1000: move firmware API struct's to separate header file It's recommended to keep the 'struct' used for passing data to firmware in separate header file. So added 'fw.h' header file to keep struct's used to pass data to firmware. Signed-off-by: Ajay Singh Link: https://lore.kernel.org/r/20200117160157.8706-3-ajay.kathat@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/fw.h | 119 +++++++++++++++++++++++++++++ drivers/staging/wilc1000/hif.c | 88 --------------------- drivers/staging/wilc1000/hif.h | 19 ----- drivers/staging/wilc1000/netdev.h | 1 - drivers/staging/wilc1000/wlan_if.h | 1 + 5 files changed, 120 insertions(+), 108 deletions(-) create mode 100644 drivers/staging/wilc1000/fw.h diff --git a/drivers/staging/wilc1000/fw.h b/drivers/staging/wilc1000/fw.h new file mode 100644 index 000000000000..21d71a9e8b47 --- /dev/null +++ b/drivers/staging/wilc1000/fw.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ + +#ifndef WILC_FW_H +#define WILC_FW_H + +#include + +#define WILC_MAX_NUM_STA 9 +#define WILC_MAX_RATES_SUPPORTED 12 +#define WILC_MAX_NUM_PMKIDS 16 +#define WILC_MAX_NUM_SCANNED_CH 14 + +struct assoc_resp { + __le16 capab_info; + __le16 status_code; + __le16 aid; +} __packed; + +struct wilc_pmkid { + u8 bssid[ETH_ALEN]; + u8 pmkid[WLAN_PMKID_LEN]; +} __packed; + +struct wilc_pmkid_attr { + u8 numpmkid; + struct wilc_pmkid pmkidlist[WILC_MAX_NUM_PMKIDS]; +} __packed; + +struct wilc_reg_frame { + u8 reg; + u8 reg_id; + __le16 frame_type; +} __packed; + +struct wilc_drv_handler { + __le32 handler; + u8 mode; +} __packed; + +struct wilc_wep_key { + u8 index; + u8 key_len; + u8 key[0]; +} __packed; + +struct wilc_sta_wpa_ptk { + u8 mac_addr[ETH_ALEN]; + u8 key_len; + u8 key[0]; +} __packed; + +struct wilc_ap_wpa_ptk { + u8 mac_addr[ETH_ALEN]; + u8 index; + u8 key_len; + u8 key[0]; +} __packed; + +struct wilc_gtk_key { + u8 mac_addr[ETH_ALEN]; + u8 rsc[8]; + u8 index; + u8 key_len; + u8 key[0]; +} __packed; + +struct wilc_op_mode { + __le32 mode; +} __packed; + +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; + u8 supp_rates[WILC_MAX_RATES_SUPPORTED + 1]; + u8 wmm_cap; + u8 uapsd_cap; + u8 ht_capable; + u8 rsn_found; + u8 rsn_grp_policy; + u8 mode_802_11i; + u8 p_suites[3]; + u8 akm_suites[3]; + u8 rsn_cap[2]; + u8 noa_enabled; + __le32 tsf_lo; + u8 idx; + u8 opp_enabled; + union { + struct wilc_noa_opp_disable opp_dis; + struct wilc_noa_opp_enable opp_en; + }; +} __packed; +#endif diff --git a/drivers/staging/wilc1000/hif.c b/drivers/staging/wilc1000/hif.c index 349e45d58ec9..1ee3d7274bd6 100644 --- a/drivers/staging/wilc1000/hif.c +++ b/drivers/staging/wilc1000/hif.c @@ -10,7 +10,6 @@ #define WILC_HIF_CONNECT_TIMEOUT_MS 9500 #define WILC_FALSE_FRMWR_CHANNEL 100 -#define WILC_MAX_RATES_SUPPORTED 12 struct wilc_rcvd_mac_info { u8 status; @@ -27,48 +26,6 @@ struct wilc_del_all_sta { u8 mac[WILC_MAX_NUM_STA][ETH_ALEN]; }; -struct wilc_op_mode { - __le32 mode; -}; - -struct wilc_reg_frame { - u8 reg; - u8 reg_id; - __le16 frame_type; -} __packed; - -struct wilc_drv_handler { - __le32 handler; - u8 mode; -} __packed; - -struct wilc_wep_key { - u8 index; - u8 key_len; - u8 key[0]; -} __packed; - -struct wilc_sta_wpa_ptk { - u8 mac_addr[ETH_ALEN]; - u8 key_len; - u8 key[0]; -} __packed; - -struct wilc_ap_wpa_ptk { - u8 mac_addr[ETH_ALEN]; - u8 index; - u8 key_len; - u8 key[0]; -} __packed; - -struct wilc_gtk_key { - u8 mac_addr[ETH_ALEN]; - u8 rsc[8]; - u8 index; - u8 key_len; - u8 key[0]; -} __packed; - union wilc_message_body { struct wilc_rcvd_net_info net_info; struct wilc_rcvd_mac_info mac_info; @@ -86,51 +43,6 @@ struct host_if_msg { bool is_sync; }; -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; - u8 supp_rates[WILC_MAX_RATES_SUPPORTED + 1]; - u8 wmm_cap; - u8 uapsd_cap; - u8 ht_capable; - u8 rsn_found; - u8 rsn_grp_policy; - u8 mode_802_11i; - u8 p_suites[3]; - u8 akm_suites[3]; - u8 rsn_cap[2]; - u8 noa_enabled; - __le32 tsf_lo; - u8 idx; - u8 opp_enabled; - union { - struct wilc_noa_opp_disable opp_dis; - struct wilc_noa_opp_enable opp_en; - }; -} __packed; - /* 'msg' should be free by the caller for syc */ static struct host_if_msg* wilc_alloc_work(struct wilc_vif *vif, void (*work_fun)(struct work_struct *), diff --git a/drivers/staging/wilc1000/hif.h b/drivers/staging/wilc1000/hif.h index 22ee6fffd599..db9179171f05 100644 --- a/drivers/staging/wilc1000/hif.h +++ b/drivers/staging/wilc1000/hif.h @@ -17,14 +17,11 @@ enum { WILC_CLIENT_MODE = 0x4 }; -#define WILC_MAX_NUM_STA 9 -#define WILC_MAX_NUM_SCANNED_CH 14 #define WILC_MAX_NUM_PROBED_SSID 10 #define WILC_TX_MIC_KEY_LEN 8 #define WILC_RX_MIC_KEY_LEN 8 -#define WILC_MAX_NUM_PMKIDS 16 #define WILC_ADD_STA_LENGTH 40 #define WILC_NUM_CONCURRENT_IFC 2 @@ -35,12 +32,6 @@ enum { #define WILC_MAX_ASSOC_RESP_FRAME_SIZE 256 -struct assoc_resp { - __le16 capab_info; - __le16 status_code; - __le16 aid; -} __packed; - struct rf_info { u8 link_speed; s8 rssi; @@ -59,16 +50,6 @@ enum host_if_state { HOST_IF_FORCE_32BIT = 0xFFFFFFFF }; -struct wilc_pmkid { - u8 bssid[ETH_ALEN]; - u8 pmkid[WLAN_PMKID_LEN]; -} __packed; - -struct wilc_pmkid_attr { - u8 numpmkid; - struct wilc_pmkid pmkidlist[WILC_MAX_NUM_PMKIDS]; -} __packed; - struct cfg_param_attr { u32 flag; u16 short_retry_limit; diff --git a/drivers/staging/wilc1000/netdev.h b/drivers/staging/wilc1000/netdev.h index cd8f0d72caaa..d5f7a6037fbc 100644 --- a/drivers/staging/wilc1000/netdev.h +++ b/drivers/staging/wilc1000/netdev.h @@ -21,7 +21,6 @@ #define FLOW_CONTROL_LOWER_THRESHOLD 128 #define FLOW_CONTROL_UPPER_THRESHOLD 256 -#define WILC_MAX_NUM_PMKIDS 16 #define PMKID_FOUND 1 #define NUM_STA_ASSOCIATED 8 diff --git a/drivers/staging/wilc1000/wlan_if.h b/drivers/staging/wilc1000/wlan_if.h index 7c7ee66c35f5..f85fd575136d 100644 --- a/drivers/staging/wilc1000/wlan_if.h +++ b/drivers/staging/wilc1000/wlan_if.h @@ -8,6 +8,7 @@ #define WILC_WLAN_IF_H #include +#include "fw.h" /******************************************** * From 1d58fec42fdf6098d8e34c679d3377bb87866add Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Fri, 17 Jan 2020 10:31:26 +0000 Subject: [PATCH 340/353] staging: wilc1000: added 'wilc_' prefix for 'struct assoc_resp' name Use 'wilc_' prefix for 'assoc_resp' struct to have proper naming convention. Signed-off-by: Ajay Singh Link: https://lore.kernel.org/r/20200117160157.8706-4-ajay.kathat@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/fw.h | 2 +- drivers/staging/wilc1000/hif.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/fw.h b/drivers/staging/wilc1000/fw.h index 21d71a9e8b47..a76e1dea4345 100644 --- a/drivers/staging/wilc1000/fw.h +++ b/drivers/staging/wilc1000/fw.h @@ -14,7 +14,7 @@ #define WILC_MAX_NUM_PMKIDS 16 #define WILC_MAX_NUM_SCANNED_CH 14 -struct assoc_resp { +struct wilc_assoc_resp { __le16 capab_info; __le16 status_code; __le16 aid; diff --git a/drivers/staging/wilc1000/hif.c b/drivers/staging/wilc1000/hif.c index 1ee3d7274bd6..658790bd465b 100644 --- a/drivers/staging/wilc1000/hif.c +++ b/drivers/staging/wilc1000/hif.c @@ -552,7 +552,7 @@ static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, { u8 *ies; u16 ies_len; - struct assoc_resp *res = (struct assoc_resp *)buffer; + struct wilc_assoc_resp *res = (struct wilc_assoc_resp *)buffer; ret_conn_info->status = le16_to_cpu(res->status_code); if (ret_conn_info->status == WLAN_STATUS_SUCCESS) { From b17028d289d37e828a66a6cfd614cd4723334ace Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Fri, 17 Jan 2020 10:31:27 +0000 Subject: [PATCH 341/353] staging: wilc1000: remove unused code prior to throughput enhancement in SPI The firmware now uses throughput enhancement code by default for SPI so remove the previous implementation as its not used anymore. Removed the use of 'has_thrpt_enh' element as its always true. Signed-off-by: Ajay Singh Link: https://lore.kernel.org/r/20200117160157.8706-5-ajay.kathat@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/spi.c | 143 +-------------------------------- 1 file changed, 4 insertions(+), 139 deletions(-) diff --git a/drivers/staging/wilc1000/spi.c b/drivers/staging/wilc1000/spi.c index 8694ab5fcb22..4b883a933b44 100644 --- a/drivers/staging/wilc1000/spi.c +++ b/drivers/staging/wilc1000/spi.c @@ -13,7 +13,6 @@ struct wilc_spi { int crc_off; int nint; - int has_thrpt_enh; }; static const struct wilc_hif_func wilc_hif_spi; @@ -897,8 +896,6 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) return 0; } - spi_priv->has_thrpt_enh = 1; - isinit = 1; return 1; @@ -906,154 +903,22 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) static int wilc_spi_read_size(struct wilc *wilc, u32 *size) { - struct spi_device *spi = to_spi_device(wilc->dev); - struct wilc_spi *spi_priv = wilc->bus_data; int ret; - if (spi_priv->has_thrpt_enh) { - ret = spi_internal_read(wilc, 0xe840 - WILC_SPI_REG_BASE, - size); - *size = *size & IRQ_DMA_WD_CNT_MASK; - } else { - u32 tmp; - u32 byte_cnt; - - ret = wilc_spi_read_reg(wilc, WILC_VMM_TO_HOST_SIZE, - &byte_cnt); - if (!ret) { - dev_err(&spi->dev, - "Failed read WILC_VMM_TO_HOST_SIZE ...\n"); - return ret; - } - tmp = (byte_cnt >> 2) & IRQ_DMA_WD_CNT_MASK; - *size = tmp; - } + ret = spi_internal_read(wilc, 0xe840 - WILC_SPI_REG_BASE, size); + *size = *size & IRQ_DMA_WD_CNT_MASK; return ret; } static int wilc_spi_read_int(struct wilc *wilc, u32 *int_status) { - struct spi_device *spi = to_spi_device(wilc->dev); - struct wilc_spi *spi_priv = wilc->bus_data; - int ret; - u32 tmp; - u32 byte_cnt; - bool unexpected_irq; - int j; - u32 unknown_mask; - u32 irq_flags; - int k = IRG_FLAGS_OFFSET + 5; - - if (spi_priv->has_thrpt_enh) - return spi_internal_read(wilc, 0xe840 - WILC_SPI_REG_BASE, - int_status); - ret = wilc_spi_read_reg(wilc, WILC_VMM_TO_HOST_SIZE, &byte_cnt); - if (!ret) { - dev_err(&spi->dev, - "Failed read WILC_VMM_TO_HOST_SIZE ...\n"); - return ret; - } - tmp = (byte_cnt >> 2) & IRQ_DMA_WD_CNT_MASK; - - j = 0; - do { - wilc_spi_read_reg(wilc, 0x1a90, &irq_flags); - tmp |= ((irq_flags >> 27) << IRG_FLAGS_OFFSET); - - if (spi_priv->nint > 5) { - wilc_spi_read_reg(wilc, 0x1a94, &irq_flags); - tmp |= (((irq_flags >> 0) & 0x7) << k); - } - - unknown_mask = ~((1ul << spi_priv->nint) - 1); - - unexpected_irq = (tmp >> IRG_FLAGS_OFFSET) & unknown_mask; - if (unexpected_irq) { - dev_err(&spi->dev, - "Unexpected interrupt(2):j=%d,tmp=%x,mask=%x\n", - j, tmp, unknown_mask); - } - - j++; - } while (unexpected_irq); - - *int_status = tmp; - - return ret; + return spi_internal_read(wilc, 0xe840 - WILC_SPI_REG_BASE, int_status); } static int wilc_spi_clear_int_ext(struct wilc *wilc, u32 val) { - struct spi_device *spi = to_spi_device(wilc->dev); - struct wilc_spi *spi_priv = wilc->bus_data; - int ret; - u32 flags; - u32 tbl_ctl; - - if (spi_priv->has_thrpt_enh) { - return spi_internal_write(wilc, 0xe844 - WILC_SPI_REG_BASE, - val); - } - - flags = val & (BIT(MAX_NUM_INT) - 1); - if (flags) { - int i; - - ret = 1; - for (i = 0; i < spi_priv->nint; i++) { - /* - * No matter what you write 1 or 0, - * it will clear interrupt. - */ - if (flags & 1) - ret = wilc_spi_write_reg(wilc, - 0x10c8 + i * 4, 1); - if (!ret) - break; - flags >>= 1; - } - if (!ret) { - dev_err(&spi->dev, - "Failed wilc_spi_write_reg, set reg %x ...\n", - 0x10c8 + i * 4); - return ret; - } - for (i = spi_priv->nint; i < MAX_NUM_INT; i++) { - if (flags & 1) - dev_err(&spi->dev, - "Unexpected interrupt cleared %d...\n", - i); - flags >>= 1; - } - } - - tbl_ctl = 0; - /* select VMM table 0 */ - if (val & SEL_VMM_TBL0) - tbl_ctl |= BIT(0); - /* select VMM table 1 */ - if (val & SEL_VMM_TBL1) - tbl_ctl |= BIT(1); - - ret = wilc_spi_write_reg(wilc, WILC_VMM_TBL_CTL, tbl_ctl); - if (!ret) { - dev_err(&spi->dev, "fail write reg vmm_tbl_ctl...\n"); - return ret; - } - - if (val & EN_VMM) { - /* - * enable vmm transfer. - */ - ret = wilc_spi_write_reg(wilc, WILC_VMM_CORE_CTL, 1); - if (!ret) { - dev_err(&spi->dev, "fail write reg vmm_core_ctl...\n"); - return ret; - } - } - - return ret; + return spi_internal_write(wilc, 0xe844 - WILC_SPI_REG_BASE, val); } static int wilc_spi_sync_ext(struct wilc *wilc, int nint) From 0443b3f4436321e1098fdf74432c8867016339da Mon Sep 17 00:00:00 2001 From: Quentin Deslandes Date: Tue, 21 Jan 2020 10:40:24 +0000 Subject: [PATCH 342/353] staging: axis-fifo: replace spinlock with mutex Following the device's documentation guidance, reading a packet from the device or writing a packet to it must be atomic. Previously, only reading device's vacancy (before writing on it) or occupancy (before reading from it) was locked. Hence, effectively reading the packet or writing the packet wasn't locked at all. However, reading a packet (and writing one, to a lesser extent) requires to read 3 different registers in a specific order, without missing one or else we should reset the device. This patch fixes the device's locking mechanism on the FIFO character device. As the device was using copy_from_user() and copy_to_user(), we need to replace spinlocks with mutexes. Signed-off-by: Quentin Deslandes Link: https://lore.kernel.org/r/20200121103958.12941-1-quentin.deslandes@itdev.co.uk Signed-off-by: Greg Kroah-Hartman --- drivers/staging/axis-fifo/axis-fifo.c | 162 ++++++++++++++++---------- 1 file changed, 102 insertions(+), 60 deletions(-) diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c index 39e6c59df1e9..5801067e7c1b 100644 --- a/drivers/staging/axis-fifo/axis-fifo.c +++ b/drivers/staging/axis-fifo/axis-fifo.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include #include @@ -133,9 +133,9 @@ struct axis_fifo { int has_tx_fifo; /* whether the IP has the tx fifo enabled */ wait_queue_head_t read_queue; /* wait queue for asynchronos read */ - spinlock_t read_queue_lock; /* lock for reading waitqueue */ + struct mutex read_lock; /* lock for reading */ wait_queue_head_t write_queue; /* wait queue for asynchronos write */ - spinlock_t write_queue_lock; /* lock for writing waitqueue */ + struct mutex write_lock; /* lock for writing */ unsigned int write_flags; /* write file flags */ unsigned int read_flags; /* read file flags */ @@ -336,7 +336,21 @@ static void reset_ip_core(struct axis_fifo *fifo) iowrite32(XLLF_INT_ALL_MASK, fifo->base_addr + XLLF_ISR_OFFSET); } -/* reads a single packet from the fifo as dictated by the tlast signal */ +/** + * axis_fifo_write() - Read a packet from AXIS-FIFO character device. + * @f Open file. + * @buf User space buffer to read to. + * @len User space buffer length. + * @off Buffer offset. + * + * As defined by the device's documentation, we need to check the device's + * occupancy before reading the length register and then the data. All these + * operations must be executed atomically, in order and one after the other + * without missing any. + * + * Returns the number of bytes read from the device or negative error code + * on failure. + */ static ssize_t axis_fifo_read(struct file *f, char __user *buf, size_t len, loff_t *off) { @@ -350,36 +364,37 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf, u32 tmp_buf[READ_BUF_SIZE]; if (fifo->read_flags & O_NONBLOCK) { - /* opened in non-blocking mode - * return if there are no packets available + /* + * Device opened in non-blocking mode. Try to lock it and then + * check if any packet is available. */ - if (!ioread32(fifo->base_addr + XLLF_RDFO_OFFSET)) + if (!mutex_trylock(&fifo->read_lock)) return -EAGAIN; + + if (!ioread32(fifo->base_addr + XLLF_RDFO_OFFSET)) { + ret = -EAGAIN; + goto end_unlock; + } } else { /* opened in blocking mode * wait for a packet available interrupt (or timeout) * if nothing is currently available */ - spin_lock_irq(&fifo->read_queue_lock); - ret = wait_event_interruptible_lock_irq_timeout - (fifo->read_queue, - ioread32(fifo->base_addr + XLLF_RDFO_OFFSET), - fifo->read_queue_lock, - (read_timeout >= 0) ? msecs_to_jiffies(read_timeout) : + mutex_lock(&fifo->read_lock); + ret = wait_event_interruptible_timeout(fifo->read_queue, + ioread32(fifo->base_addr + XLLF_RDFO_OFFSET), + (read_timeout >= 0) ? msecs_to_jiffies(read_timeout) : MAX_SCHEDULE_TIMEOUT); - spin_unlock_irq(&fifo->read_queue_lock); - if (ret == 0) { - /* timeout occurred */ - dev_dbg(fifo->dt_device, "read timeout"); - return -EAGAIN; - } else if (ret == -ERESTARTSYS) { - /* signal received */ - return -ERESTARTSYS; - } else if (ret < 0) { - dev_err(fifo->dt_device, "wait_event_interruptible_timeout() error in read (ret=%i)\n", - ret); - return ret; + if (ret <= 0) { + if (ret == 0) { + ret = -EAGAIN; + } else if (ret != -ERESTARTSYS) { + dev_err(fifo->dt_device, "wait_event_interruptible_timeout() error in read (ret=%i)\n", + ret); + } + + goto end_unlock; } } @@ -387,14 +402,16 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf, if (!bytes_available) { dev_err(fifo->dt_device, "received a packet of length 0 - fifo core will be reset\n"); reset_ip_core(fifo); - return -EIO; + ret = -EIO; + goto end_unlock; } if (bytes_available > len) { dev_err(fifo->dt_device, "user read buffer too small (available bytes=%zu user buffer bytes=%zu) - fifo core will be reset\n", bytes_available, len); reset_ip_core(fifo); - return -EINVAL; + ret = -EINVAL; + goto end_unlock; } if (bytes_available % sizeof(u32)) { @@ -403,7 +420,8 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf, */ dev_err(fifo->dt_device, "received a packet that isn't word-aligned - fifo core will be reset\n"); reset_ip_core(fifo); - return -EIO; + ret = -EIO; + goto end_unlock; } words_available = bytes_available / sizeof(u32); @@ -423,16 +441,37 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf, if (copy_to_user(buf + copied * sizeof(u32), tmp_buf, copy * sizeof(u32))) { reset_ip_core(fifo); - return -EFAULT; + ret = -EFAULT; + goto end_unlock; } copied += copy; words_available -= copy; } - return bytes_available; + ret = bytes_available; + +end_unlock: + mutex_unlock(&fifo->read_lock); + + return ret; } +/** + * axis_fifo_write() - Write buffer to AXIS-FIFO character device. + * @f Open file. + * @buf User space buffer to write to the device. + * @len User space buffer length. + * @off Buffer offset. + * + * As defined by the device's documentation, we need to write to the device's + * data buffer then to the device's packet length register atomically. Also, + * we need to lock before checking if the device has available space to avoid + * any concurrency issue. + * + * Returns the number of bytes written to the device or negative error code + * on failure. + */ static ssize_t axis_fifo_write(struct file *f, const char __user *buf, size_t len, loff_t *off) { @@ -465,12 +504,17 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf, } if (fifo->write_flags & O_NONBLOCK) { - /* opened in non-blocking mode - * return if there is not enough room available in the fifo + /* + * Device opened in non-blocking mode. Try to lock it and then + * check if there is any room to write the given buffer. */ + if (!mutex_trylock(&fifo->write_lock)) + return -EAGAIN; + if (words_to_write > ioread32(fifo->base_addr + XLLF_TDFV_OFFSET)) { - return -EAGAIN; + ret = -EAGAIN; + goto end_unlock; } } else { /* opened in blocking mode */ @@ -478,30 +522,22 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf, /* wait for an interrupt (or timeout) if there isn't * currently enough room in the fifo */ - spin_lock_irq(&fifo->write_queue_lock); - ret = wait_event_interruptible_lock_irq_timeout - (fifo->write_queue, - ioread32(fifo->base_addr + XLLF_TDFV_OFFSET) + mutex_lock(&fifo->write_lock); + ret = wait_event_interruptible_timeout(fifo->write_queue, + ioread32(fifo->base_addr + XLLF_TDFV_OFFSET) >= words_to_write, - fifo->write_queue_lock, - (write_timeout >= 0) ? - msecs_to_jiffies(write_timeout) : + (write_timeout >= 0) ? msecs_to_jiffies(write_timeout) : MAX_SCHEDULE_TIMEOUT); - spin_unlock_irq(&fifo->write_queue_lock); - if (ret == 0) { - /* timeout occurred */ - dev_dbg(fifo->dt_device, "write timeout\n"); - return -EAGAIN; - } else if (ret == -ERESTARTSYS) { - /* signal received */ - return -ERESTARTSYS; - } else if (ret < 0) { - /* unknown error */ - dev_err(fifo->dt_device, - "wait_event_interruptible_timeout() error in write (ret=%i)\n", - ret); - return ret; + if (ret <= 0) { + if (ret == 0) { + ret = -EAGAIN; + } else if (ret != -ERESTARTSYS) { + dev_err(fifo->dt_device, "wait_event_interruptible_timeout() error in write (ret=%i)\n", + ret); + } + + goto end_unlock; } } @@ -515,7 +551,8 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf, if (copy_from_user(tmp_buf, buf + copied * sizeof(u32), copy * sizeof(u32))) { reset_ip_core(fifo); - return -EFAULT; + ret = -EFAULT; + goto end_unlock; } for (i = 0; i < copy; i++) @@ -526,10 +563,15 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf, words_to_write -= copy; } - /* write packet size to fifo */ - iowrite32(copied * sizeof(u32), fifo->base_addr + XLLF_TLR_OFFSET); + ret = copied * sizeof(u32); - return (ssize_t)copied * sizeof(u32); + /* write packet size to fifo */ + iowrite32(ret, fifo->base_addr + XLLF_TLR_OFFSET); + +end_unlock: + mutex_unlock(&fifo->write_lock); + + return ret; } static irqreturn_t axis_fifo_irq(int irq, void *dw) @@ -789,8 +831,8 @@ static int axis_fifo_probe(struct platform_device *pdev) init_waitqueue_head(&fifo->read_queue); init_waitqueue_head(&fifo->write_queue); - spin_lock_init(&fifo->read_queue_lock); - spin_lock_init(&fifo->write_queue_lock); + mutex_init(&fifo->read_lock); + mutex_init(&fifo->write_lock); /* ---------------------------- * init device memory space From 7a80aa23d0f0f52478339840577137f556bf9121 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 23 Jan 2020 12:50:47 +0000 Subject: [PATCH 343/353] staging: wilc1000: return zero on success and non-zero on function failure Some of the HIF layer API's return zero for failure and non-zero for success condition. Now, modified the functions to return zero for success and non-zero for failure as its recommended approach suggested in [1]. 1. https://lore.kernel.org/driverdev-devel/20191113183322.a54mh2w6dulklgsd@kili.mountain/ Signed-off-by: Ajay Singh Link: https://lore.kernel.org/r/20200123182129.4053-1-ajay.kathat@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/netdev.c | 45 +++----- drivers/staging/wilc1000/sdio.c | 178 +++++++++++++----------------- drivers/staging/wilc1000/spi.c | 138 ++++++++++++----------- drivers/staging/wilc1000/wlan.c | 75 +++++++------ 4 files changed, 197 insertions(+), 239 deletions(-) diff --git a/drivers/staging/wilc1000/netdev.c b/drivers/staging/wilc1000/netdev.c index 960dbc8d5173..0f48e74aa3ea 100644 --- a/drivers/staging/wilc1000/netdev.c +++ b/drivers/staging/wilc1000/netdev.c @@ -183,7 +183,7 @@ static int wilc_wlan_get_firmware(struct net_device *dev) { struct wilc_vif *vif = netdev_priv(dev); struct wilc *wilc = vif->wilc; - int chip_id, ret = 0; + int chip_id; const struct firmware *wilc_firmware; char *firmware; @@ -198,14 +198,11 @@ static int wilc_wlan_get_firmware(struct net_device *dev) if (request_firmware(&wilc_firmware, firmware, wilc->dev) != 0) { netdev_err(dev, "%s - firmware not available\n", firmware); - ret = -1; - goto fail; + return -EINVAL; } wilc->firmware = wilc_firmware; -fail: - - return ret; + return 0; } static int wilc_start_firmware(struct net_device *dev) @@ -215,7 +212,7 @@ static int wilc_start_firmware(struct net_device *dev) int ret = 0; ret = wilc_wlan_start(wilc); - if (ret < 0) + if (ret) return ret; if (!wait_for_completion_timeout(&wilc->sync_event, @@ -238,7 +235,7 @@ static int wilc1000_firmware_download(struct net_device *dev) ret = wilc_wlan_firmware_download(wilc, wilc->firmware->data, wilc->firmware->size); - if (ret < 0) + if (ret) return ret; release_firmware(wilc->firmware); @@ -417,7 +414,7 @@ static int wilc_init_fw_config(struct net_device *dev, struct wilc_vif *vif) return 0; fail: - return -1; + return -EINVAL; } static void wlan_deinitialize_threads(struct net_device *dev) @@ -497,14 +494,12 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) wl->close = 0; ret = wilc_wlan_init(dev); - if (ret < 0) - return -EIO; + if (ret) + return ret; ret = wlan_initialize_threads(dev); - if (ret < 0) { - ret = -EIO; + if (ret) goto fail_wilc_wlan; - } if (wl->gpio_irq && init_irq(dev)) { ret = -EIO; @@ -518,22 +513,17 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) goto fail_irq_init; } - if (wilc_wlan_get_firmware(dev)) { - ret = -EIO; + ret = wilc_wlan_get_firmware(dev); + if (ret) goto fail_irq_enable; - } ret = wilc1000_firmware_download(dev); - if (ret < 0) { - ret = -EIO; + if (ret) goto fail_irq_enable; - } ret = wilc_start_firmware(dev); - if (ret < 0) { - ret = -EIO; + if (ret) goto fail_irq_enable; - } if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) { int size; @@ -545,11 +535,10 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) firmware_ver[size] = '\0'; netdev_dbg(dev, "Firmware Ver = %s\n", firmware_ver); } - ret = wilc_init_fw_config(dev, vif); - if (ret < 0) { + ret = wilc_init_fw_config(dev, vif); + if (ret) { netdev_err(dev, "Failed to configure firmware\n"); - ret = -EIO; goto fail_fw_start; } wl->initialized = true; @@ -600,11 +589,11 @@ static int wilc_mac_open(struct net_device *ndev) netdev_dbg(ndev, "MAC OPEN[%p]\n", ndev); ret = wilc_init_host_int(ndev); - if (ret < 0) + if (ret) return ret; ret = wilc_wlan_initialize(ndev, vif); - if (ret < 0) { + if (ret) { wilc_deinit_host_int(ndev); return ret; } diff --git a/drivers/staging/wilc1000/sdio.c b/drivers/staging/wilc1000/sdio.c index 319e039380b0..ca99335687c4 100644 --- a/drivers/staging/wilc1000/sdio.c +++ b/drivers/staging/wilc1000/sdio.c @@ -273,7 +273,7 @@ static int wilc_sdio_set_func0_csa_address(struct wilc *wilc, u32 adr) ret = wilc_sdio_cmd52(wilc, &cmd); if (ret) { dev_err(&func->dev, "Failed cmd52, set 0x10c data...\n"); - goto fail; + return ret; } cmd.address = 0x10d; @@ -281,7 +281,7 @@ static int wilc_sdio_set_func0_csa_address(struct wilc *wilc, u32 adr) ret = wilc_sdio_cmd52(wilc, &cmd); if (ret) { dev_err(&func->dev, "Failed cmd52, set 0x10d data...\n"); - goto fail; + return ret; } cmd.address = 0x10e; @@ -289,11 +289,9 @@ static int wilc_sdio_set_func0_csa_address(struct wilc *wilc, u32 adr) ret = wilc_sdio_cmd52(wilc, &cmd); if (ret) { dev_err(&func->dev, "Failed cmd52, set 0x10e data...\n"); - goto fail; + return ret; } - return 1; -fail: return 0; } @@ -311,7 +309,7 @@ static int wilc_sdio_set_func0_block_size(struct wilc *wilc, u32 block_size) ret = wilc_sdio_cmd52(wilc, &cmd); if (ret) { dev_err(&func->dev, "Failed cmd52, set 0x10 data...\n"); - goto fail; + return ret; } cmd.address = 0x11; @@ -319,11 +317,9 @@ static int wilc_sdio_set_func0_block_size(struct wilc *wilc, u32 block_size) ret = wilc_sdio_cmd52(wilc, &cmd); if (ret) { dev_err(&func->dev, "Failed cmd52, set 0x11 data...\n"); - goto fail; + return ret; } - return 1; -fail: return 0; } @@ -347,18 +343,16 @@ static int wilc_sdio_set_func1_block_size(struct wilc *wilc, u32 block_size) ret = wilc_sdio_cmd52(wilc, &cmd); if (ret) { dev_err(&func->dev, "Failed cmd52, set 0x110 data...\n"); - goto fail; + return ret; } cmd.address = 0x111; cmd.data = (u8)(block_size >> 8); ret = wilc_sdio_cmd52(wilc, &cmd); if (ret) { dev_err(&func->dev, "Failed cmd52, set 0x111 data...\n"); - goto fail; + return ret; } - return 1; -fail: return 0; } @@ -384,19 +378,18 @@ static int wilc_sdio_write_reg(struct wilc *wilc, u32 addr, u32 data) cmd.address = addr; cmd.data = data; ret = wilc_sdio_cmd52(wilc, &cmd); - if (ret) { + if (ret) dev_err(&func->dev, "Failed cmd 52, read reg (%08x) ...\n", addr); - goto fail; - } } else { struct sdio_cmd53 cmd; /** * set the AHB address **/ - if (!wilc_sdio_set_func0_csa_address(wilc, addr)) - goto fail; + ret = wilc_sdio_set_func0_csa_address(wilc, addr); + if (ret) + return ret; cmd.read_write = 1; cmd.function = 0; @@ -407,18 +400,12 @@ static int wilc_sdio_write_reg(struct wilc *wilc, u32 addr, u32 data) cmd.buffer = (u8 *)&data; cmd.block_size = sdio_priv->block_size; ret = wilc_sdio_cmd53(wilc, &cmd); - if (ret) { + if (ret) dev_err(&func->dev, "Failed cmd53, write reg (%08x)...\n", addr); - goto fail; - } } - return 1; - -fail: - - return 0; + return ret; } static int wilc_sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) @@ -470,14 +457,15 @@ static int wilc_sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) cmd.buffer = buf; cmd.block_size = block_size; if (addr > 0) { - if (!wilc_sdio_set_func0_csa_address(wilc, addr)) - goto fail; + ret = wilc_sdio_set_func0_csa_address(wilc, addr); + if (ret) + return ret; } ret = wilc_sdio_cmd53(wilc, &cmd); if (ret) { dev_err(&func->dev, "Failed cmd53 [%x], block send...\n", addr); - goto fail; + return ret; } if (addr > 0) addr += nblk * block_size; @@ -493,21 +481,18 @@ static int wilc_sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) cmd.block_size = block_size; if (addr > 0) { - if (!wilc_sdio_set_func0_csa_address(wilc, addr)) - goto fail; + ret = wilc_sdio_set_func0_csa_address(wilc, addr); + if (ret) + return ret; } ret = wilc_sdio_cmd53(wilc, &cmd); if (ret) { dev_err(&func->dev, "Failed cmd53 [%x], bytes send...\n", addr); - goto fail; + return ret; } } - return 1; - -fail: - return 0; } @@ -528,14 +513,15 @@ static int wilc_sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data) if (ret) { dev_err(&func->dev, "Failed cmd 52, read reg (%08x) ...\n", addr); - goto fail; + return ret; } *data = cmd.data; } else { struct sdio_cmd53 cmd; - if (!wilc_sdio_set_func0_csa_address(wilc, addr)) - goto fail; + ret = wilc_sdio_set_func0_csa_address(wilc, addr); + if (ret) + return ret; cmd.read_write = 0; cmd.function = 0; @@ -550,16 +536,11 @@ static int wilc_sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data) if (ret) { dev_err(&func->dev, "Failed cmd53, read reg (%08x)...\n", addr); - goto fail; + return ret; } } le32_to_cpus(data); - - return 1; - -fail: - return 0; } @@ -612,14 +593,15 @@ static int wilc_sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) cmd.buffer = buf; cmd.block_size = block_size; if (addr > 0) { - if (!wilc_sdio_set_func0_csa_address(wilc, addr)) - goto fail; + ret = wilc_sdio_set_func0_csa_address(wilc, addr); + if (ret) + return ret; } ret = wilc_sdio_cmd53(wilc, &cmd); if (ret) { dev_err(&func->dev, "Failed cmd53 [%x], block read...\n", addr); - goto fail; + return ret; } if (addr > 0) addr += nblk * block_size; @@ -635,21 +617,18 @@ static int wilc_sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) cmd.block_size = block_size; if (addr > 0) { - if (!wilc_sdio_set_func0_csa_address(wilc, addr)) - goto fail; + ret = wilc_sdio_set_func0_csa_address(wilc, addr); + if (ret) + return ret; } ret = wilc_sdio_cmd53(wilc, &cmd); if (ret) { dev_err(&func->dev, "Failed cmd53 [%x], bytes read...\n", addr); - goto fail; + return ret; } } - return 1; - -fail: - return 0; } @@ -661,7 +640,7 @@ fail: static int wilc_sdio_deinit(struct wilc *wilc) { - return 1; + return 0; } static int wilc_sdio_init(struct wilc *wilc, bool resume) @@ -686,15 +665,16 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume) ret = wilc_sdio_cmd52(wilc, &cmd); if (ret) { dev_err(&func->dev, "Fail cmd 52, enable csa...\n"); - goto fail; + return ret; } /** * function 0 block size **/ - if (!wilc_sdio_set_func0_block_size(wilc, WILC_SDIO_BLOCK_SIZE)) { + ret = wilc_sdio_set_func0_block_size(wilc, WILC_SDIO_BLOCK_SIZE); + if (ret) { dev_err(&func->dev, "Fail cmd 52, set func 0 block size...\n"); - goto fail; + return ret; } sdio_priv->block_size = WILC_SDIO_BLOCK_SIZE; @@ -710,7 +690,7 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume) if (ret) { dev_err(&func->dev, "Fail cmd 52, set IOE register...\n"); - goto fail; + return ret; } /** @@ -727,7 +707,7 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume) if (ret) { dev_err(&func->dev, "Fail cmd 52, get IOR register...\n"); - goto fail; + return ret; } if (cmd.data == 0x2) break; @@ -735,15 +715,16 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume) if (loop <= 0) { dev_err(&func->dev, "Fail func 1 is not ready...\n"); - goto fail; + return -EINVAL; } /** * func 1 is ready, set func 1 block size **/ - if (!wilc_sdio_set_func1_block_size(wilc, WILC_SDIO_BLOCK_SIZE)) { + ret = wilc_sdio_set_func1_block_size(wilc, WILC_SDIO_BLOCK_SIZE); + if (ret) { dev_err(&func->dev, "Fail set func 1 block size...\n"); - goto fail; + return ret; } /** @@ -757,16 +738,17 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume) ret = wilc_sdio_cmd52(wilc, &cmd); if (ret) { dev_err(&func->dev, "Fail cmd 52, set IEN register...\n"); - goto fail; + return ret; } /** * make sure can read back chip id correctly **/ if (!resume) { - if (!wilc_sdio_read_reg(wilc, 0x1000, &chipid)) { + ret = wilc_sdio_read_reg(wilc, 0x1000, &chipid); + if (ret) { dev_err(&func->dev, "Fail cmd read chip id...\n"); - goto fail; + return ret; } dev_err(&func->dev, "chipid (%08x)\n", chipid); if ((chipid & 0xfff) > 0x2a0) @@ -777,10 +759,6 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume) sdio_priv->has_thrpt_enh3); } - return 1; - -fail: - return 0; } @@ -806,7 +784,7 @@ static int wilc_sdio_read_size(struct wilc *wilc, u32 *size) tmp |= (cmd.data << 8); *size = tmp; - return 1; + return 0; } static int wilc_sdio_read_int(struct wilc *wilc, u32 *int_status) @@ -865,7 +843,7 @@ static int wilc_sdio_read_int(struct wilc *wilc, u32 *int_status) *int_status = tmp; - return 1; + return 0; } static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val) @@ -909,10 +887,10 @@ static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val) dev_err(&func->dev, "Failed cmd52, set 0xf8 data (%d) ...\n", __LINE__); - goto fail; + return ret; } } - return 1; + return 0; } if (sdio_priv->irq_gpio) { /* has_thrpt_enh2 uses register 0xf8 to clear interrupts. */ @@ -926,7 +904,6 @@ static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val) if (flags) { int i; - ret = 1; for (i = 0; i < sdio_priv->nint; i++) { if (flags & 1) { struct sdio_cmd52 cmd; @@ -942,15 +919,12 @@ static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val) dev_err(&func->dev, "Failed cmd52, set 0xf8 data (%d) ...\n", __LINE__); - goto fail; + return ret; } } - if (!ret) - break; flags >>= 1; } - if (!ret) - goto fail; + for (i = sdio_priv->nint; i < MAX_NUM_INT; i++) { if (flags & 1) dev_err(&func->dev, @@ -985,11 +959,9 @@ static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val) dev_err(&func->dev, "Failed cmd52, set 0xf6 data (%d) ...\n", __LINE__); - goto fail; + return ret; } } - return 1; -fail: return 0; } @@ -1001,12 +973,12 @@ static int wilc_sdio_sync_ext(struct wilc *wilc, int nint) if (nint > MAX_NUM_INT) { dev_err(&func->dev, "Too many interrupts (%d)...\n", nint); - return 0; + return -EINVAL; } if (nint > MAX_NUN_INT_THRPT_ENH2) { dev_err(&func->dev, "Cannot support more than 5 interrupts when has_thrpt_enh2=1.\n"); - return 0; + return -EINVAL; } sdio_priv->nint = nint; @@ -1014,15 +986,15 @@ static int wilc_sdio_sync_ext(struct wilc *wilc, int nint) /** * Disable power sequencer **/ - if (!wilc_sdio_read_reg(wilc, WILC_MISC, ®)) { + if (wilc_sdio_read_reg(wilc, WILC_MISC, ®)) { dev_err(&func->dev, "Failed read misc reg...\n"); - return 0; + return -EINVAL; } reg &= ~BIT(8); - if (!wilc_sdio_write_reg(wilc, WILC_MISC, reg)) { + if (wilc_sdio_write_reg(wilc, WILC_MISC, reg)) { dev_err(&func->dev, "Failed write misc reg...\n"); - return 0; + return -EINVAL; } if (sdio_priv->irq_gpio) { @@ -1033,59 +1005,59 @@ static int wilc_sdio_sync_ext(struct wilc *wilc, int nint) * interrupt pin mux select **/ ret = wilc_sdio_read_reg(wilc, WILC_PIN_MUX_0, ®); - if (!ret) { + if (ret) { dev_err(&func->dev, "Failed read reg (%08x)...\n", WILC_PIN_MUX_0); - return 0; + return ret; } reg |= BIT(8); ret = wilc_sdio_write_reg(wilc, WILC_PIN_MUX_0, reg); - if (!ret) { + if (ret) { dev_err(&func->dev, "Failed write reg (%08x)...\n", WILC_PIN_MUX_0); - return 0; + return ret; } /** * interrupt enable **/ ret = wilc_sdio_read_reg(wilc, WILC_INTR_ENABLE, ®); - if (!ret) { + if (ret) { dev_err(&func->dev, "Failed read reg (%08x)...\n", WILC_INTR_ENABLE); - return 0; + return ret; } for (i = 0; (i < 5) && (nint > 0); i++, nint--) reg |= BIT((27 + i)); ret = wilc_sdio_write_reg(wilc, WILC_INTR_ENABLE, reg); - if (!ret) { + if (ret) { dev_err(&func->dev, "Failed write reg (%08x)...\n", WILC_INTR_ENABLE); - return 0; + return ret; } if (nint) { ret = wilc_sdio_read_reg(wilc, WILC_INTR2_ENABLE, ®); - if (!ret) { + if (ret) { dev_err(&func->dev, "Failed read reg (%08x)...\n", WILC_INTR2_ENABLE); - return 0; + return ret; } for (i = 0; (i < 3) && (nint > 0); i++, nint--) reg |= BIT(i); ret = wilc_sdio_read_reg(wilc, WILC_INTR2_ENABLE, ®); - if (!ret) { + if (ret) { dev_err(&func->dev, "Failed write reg (%08x)...\n", WILC_INTR2_ENABLE); - return 0; + return ret; } } } - return 1; + return 0; } /* Global sdio HIF function table */ diff --git a/drivers/staging/wilc1000/spi.c b/drivers/staging/wilc1000/spi.c index 4b883a933b44..3ffc7b4fddf6 100644 --- a/drivers/staging/wilc1000/spi.c +++ b/drivers/staging/wilc1000/spi.c @@ -88,11 +88,6 @@ static u8 crc7(u8 crc, const u8 *buffer, u32 len) #define CMD_SINGLE_READ 0xca #define CMD_RESET 0xcf -#define N_OK 1 -#define N_FAIL 0 -#define N_RESET -1 -#define N_RETRY -2 - #define DATA_PKT_SZ_256 256 #define DATA_PKT_SZ_512 512 #define DATA_PKT_SZ_1K 1024 @@ -299,7 +294,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, u32 len2; u8 rsp; int len = 0; - int result = N_OK; + int result = 0; int retry; u8 crc[2]; @@ -387,11 +382,11 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, break; default: - result = N_FAIL; + result = -EINVAL; break; } - if (result != N_OK) + if (result) return result; if (!spi_priv->crc_off) @@ -424,7 +419,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (len2 > ARRAY_SIZE(wb)) { dev_err(&spi->dev, "spi buffer size too small (%d) (%zu)\n", len2, ARRAY_SIZE(wb)); - return N_FAIL; + return -EINVAL; } /* zero spi write buffers. */ for (wix = len; wix < len2; wix++) @@ -433,7 +428,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (wilc_spi_tx_rx(wilc, wb, rb, len2)) { dev_err(&spi->dev, "Failed cmd write, bus error...\n"); - return N_FAIL; + return -EINVAL; } /* @@ -448,7 +443,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, dev_err(&spi->dev, "Failed cmd response, cmd (%02x), resp (%02x)\n", cmd, rsp); - return N_FAIL; + return -EINVAL; } /* @@ -458,7 +453,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (rsp != 0x00) { dev_err(&spi->dev, "Failed cmd state response state (%02x)\n", rsp); - return N_FAIL; + return -EINVAL; } if (cmd == CMD_INTERNAL_READ || cmd == CMD_SINGLE_READ || @@ -485,7 +480,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (retry <= 0) { dev_err(&spi->dev, "Error, data read response (%02x)\n", rsp); - return N_RESET; + return -EAGAIN; } } @@ -501,7 +496,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, } else { dev_err(&spi->dev, "buffer overrun when reading data.\n"); - return N_FAIL; + return -EINVAL; } if (!spi_priv->crc_off) { @@ -514,7 +509,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, } else { dev_err(&spi->dev, "buffer overrun when reading crc.\n"); - return N_FAIL; + return -EINVAL; } } } else if ((cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) { @@ -540,7 +535,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (wilc_spi_rx(wilc, &b[ix], nbytes)) { dev_err(&spi->dev, "Failed block read, bus err\n"); - return N_FAIL; + return -EINVAL; } /* @@ -549,7 +544,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (!spi_priv->crc_off && wilc_spi_rx(wilc, crc, 2)) { dev_err(&spi->dev, "Failed block crc read, bus err\n"); - return N_FAIL; + return -EINVAL; } ix += nbytes; @@ -581,14 +576,14 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (wilc_spi_rx(wilc, &rsp, 1)) { dev_err(&spi->dev, "Failed resp read, bus err\n"); - result = N_FAIL; + result = -EINVAL; break; } if (((rsp >> 4) & 0xf) == 0xf) break; } while (retry--); - if (result == N_FAIL) + if (result) break; /* @@ -597,7 +592,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (wilc_spi_rx(wilc, &b[ix], nbytes)) { dev_err(&spi->dev, "Failed block read, bus err\n"); - result = N_FAIL; + result = -EINVAL; break; } @@ -607,7 +602,7 @@ static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, if (!spi_priv->crc_off && wilc_spi_rx(wilc, crc, 2)) { dev_err(&spi->dev, "Failed block crc read, bus err\n"); - result = N_FAIL; + result = -EINVAL; break; } @@ -623,7 +618,7 @@ static int spi_data_write(struct wilc *wilc, u8 *b, u32 sz) struct spi_device *spi = to_spi_device(wilc->dev); struct wilc_spi *spi_priv = wilc->bus_data; int ix, nbytes; - int result = 1; + int result = 0; u8 cmd, order, crc[2] = {0}; /* @@ -651,7 +646,7 @@ static int spi_data_write(struct wilc *wilc, u8 *b, u32 sz) if (wilc_spi_tx(wilc, &cmd, 1)) { dev_err(&spi->dev, "Failed data block cmd write, bus error...\n"); - result = N_FAIL; + result = -EINVAL; break; } @@ -661,7 +656,7 @@ static int spi_data_write(struct wilc *wilc, u8 *b, u32 sz) if (wilc_spi_tx(wilc, &b[ix], nbytes)) { dev_err(&spi->dev, "Failed data block write, bus error...\n"); - result = N_FAIL; + result = -EINVAL; break; } @@ -671,7 +666,7 @@ static int spi_data_write(struct wilc *wilc, u8 *b, u32 sz) if (!spi_priv->crc_off) { if (wilc_spi_tx(wilc, crc, 2)) { dev_err(&spi->dev, "Failed data block crc write, bus error...\n"); - result = N_FAIL; + result = -EINVAL; break; } } @@ -700,7 +695,7 @@ static int spi_internal_write(struct wilc *wilc, u32 adr, u32 dat) cpu_to_le32s(&dat); result = spi_cmd_complete(wilc, CMD_INTERNAL_WRITE, adr, (u8 *)&dat, 4, 0); - if (result != N_OK) + if (result) dev_err(&spi->dev, "Failed internal write cmd...\n"); return result; @@ -713,14 +708,14 @@ static int spi_internal_read(struct wilc *wilc, u32 adr, u32 *data) result = spi_cmd_complete(wilc, CMD_INTERNAL_READ, adr, (u8 *)data, 4, 0); - if (result != N_OK) { + if (result) { dev_err(&spi->dev, "Failed internal read cmd...\n"); - return 0; + return result; } le32_to_cpus(data); - return 1; + return result; } /******************************************** @@ -744,7 +739,7 @@ static int wilc_spi_write_reg(struct wilc *wilc, u32 addr, u32 data) } result = spi_cmd_complete(wilc, cmd, addr, (u8 *)&data, 4, clockless); - if (result != N_OK) + if (result) dev_err(&spi->dev, "Failed cmd, write reg (%08x)...\n", addr); return result; @@ -759,23 +754,23 @@ static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) * has to be greated than 4 */ if (size <= 4) - return 0; + return -EINVAL; result = spi_cmd_complete(wilc, CMD_DMA_EXT_WRITE, addr, NULL, size, 0); - if (result != N_OK) { + if (result) { dev_err(&spi->dev, "Failed cmd, write block (%08x)...\n", addr); - return 0; + return result; } /* * Data */ result = spi_data_write(wilc, buf, size); - if (result != N_OK) + if (result) dev_err(&spi->dev, "Failed block data write...\n"); - return 1; + return result; } static int wilc_spi_read_reg(struct wilc *wilc, u32 addr, u32 *data) @@ -792,14 +787,14 @@ static int wilc_spi_read_reg(struct wilc *wilc, u32 addr, u32 *data) } result = spi_cmd_complete(wilc, cmd, addr, (u8 *)data, 4, clockless); - if (result != N_OK) { + if (result) { dev_err(&spi->dev, "Failed cmd, read reg (%08x)...\n", addr); - return 0; + return result; } le32_to_cpus(data); - return 1; + return 0; } static int wilc_spi_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) @@ -808,15 +803,13 @@ static int wilc_spi_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) int result; if (size <= 4) - return 0; + return -EINVAL; result = spi_cmd_complete(wilc, CMD_DMA_EXT_READ, addr, buf, size, 0); - if (result != N_OK) { + if (result) dev_err(&spi->dev, "Failed cmd, read block (%08x)...\n", addr); - return 0; - } - return 1; + return result; } /******************************************** @@ -830,7 +823,7 @@ static int wilc_spi_deinit(struct wilc *wilc) /* * TODO: */ - return 1; + return 0; } static int wilc_spi_init(struct wilc *wilc, bool resume) @@ -840,13 +833,14 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) u32 reg; u32 chipid; static int isinit; + int ret; if (isinit) { - if (!wilc_spi_read_reg(wilc, 0x1000, &chipid)) { + ret = wilc_spi_read_reg(wilc, 0x1000, &chipid); + if (ret) dev_err(&spi->dev, "Fail cmd read chip id...\n"); - return 0; - } - return 1; + + return ret; } /* @@ -858,7 +852,8 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) * way to reset */ /* the SPI to it's initial value. */ - if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®)) { + ret = spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®); + if (ret) { /* * Read failed. Try with CRC off. This might happen when module * is removed but chip isn't reset @@ -866,24 +861,26 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) spi_priv->crc_off = 1; dev_err(&spi->dev, "Failed read with CRC on, retrying with CRC off\n"); - if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®)) { + ret = spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®); + if (ret) { /* * Read failed with both CRC on and off, * something went bad */ dev_err(&spi->dev, "Failed internal read protocol\n"); - return 0; + return ret; } } if (spi_priv->crc_off == 0) { reg &= ~0xc; /* disable crc checking */ reg &= ~0x70; reg |= (0x5 << 4); - if (!spi_internal_write(wilc, WILC_SPI_PROTOCOL_OFFSET, reg)) { + ret = spi_internal_write(wilc, WILC_SPI_PROTOCOL_OFFSET, reg); + if (ret) { dev_err(&spi->dev, "[wilc spi %d]: Failed internal write reg\n", __LINE__); - return 0; + return ret; } spi_priv->crc_off = 1; } @@ -891,14 +888,15 @@ static int wilc_spi_init(struct wilc *wilc, bool resume) /* * make sure can read back chip id correctly */ - if (!wilc_spi_read_reg(wilc, 0x1000, &chipid)) { + ret = wilc_spi_read_reg(wilc, 0x1000, &chipid); + if (ret) { dev_err(&spi->dev, "Fail cmd read chip id...\n"); - return 0; + return ret; } isinit = 1; - return 1; + return 0; } static int wilc_spi_read_size(struct wilc *wilc, u32 *size) @@ -930,7 +928,7 @@ static int wilc_spi_sync_ext(struct wilc *wilc, int nint) if (nint > MAX_NUM_INT) { dev_err(&spi->dev, "Too many interrupts (%d)...\n", nint); - return 0; + return -EINVAL; } spi_priv->nint = nint; @@ -939,58 +937,58 @@ static int wilc_spi_sync_ext(struct wilc *wilc, int nint) * interrupt pin mux select */ ret = wilc_spi_read_reg(wilc, WILC_PIN_MUX_0, ®); - if (!ret) { + if (ret) { dev_err(&spi->dev, "Failed read reg (%08x)...\n", WILC_PIN_MUX_0); - return 0; + return ret; } reg |= BIT(8); ret = wilc_spi_write_reg(wilc, WILC_PIN_MUX_0, reg); - if (!ret) { + if (ret) { dev_err(&spi->dev, "Failed write reg (%08x)...\n", WILC_PIN_MUX_0); - return 0; + return ret; } /* * interrupt enable */ ret = wilc_spi_read_reg(wilc, WILC_INTR_ENABLE, ®); - if (!ret) { + if (ret) { dev_err(&spi->dev, "Failed read reg (%08x)...\n", WILC_INTR_ENABLE); - return 0; + return ret; } for (i = 0; (i < 5) && (nint > 0); i++, nint--) reg |= (BIT((27 + i))); ret = wilc_spi_write_reg(wilc, WILC_INTR_ENABLE, reg); - if (!ret) { + if (ret) { dev_err(&spi->dev, "Failed write reg (%08x)...\n", WILC_INTR_ENABLE); - return 0; + return ret; } if (nint) { ret = wilc_spi_read_reg(wilc, WILC_INTR2_ENABLE, ®); - if (!ret) { + if (ret) { dev_err(&spi->dev, "Failed read reg (%08x)...\n", WILC_INTR2_ENABLE); - return 0; + return ret; } for (i = 0; (i < 3) && (nint > 0); i++, nint--) reg |= BIT(i); ret = wilc_spi_read_reg(wilc, WILC_INTR2_ENABLE, ®); - if (!ret) { + if (ret) { dev_err(&spi->dev, "Failed write reg (%08x)...\n", WILC_INTR2_ENABLE); - return 0; + return ret; } } - return 1; + return 0; } /* Global spi HIF function table */ diff --git a/drivers/staging/wilc1000/wlan.c b/drivers/staging/wilc1000/wlan.c index c32af7076012..b904eda42806 100644 --- a/drivers/staging/wilc1000/wlan.c +++ b/drivers/staging/wilc1000/wlan.c @@ -534,7 +534,7 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) func = wilc->hif_func; do { ret = func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®); - if (!ret) + if (ret) break; if ((reg & 0x1) == 0) @@ -548,7 +548,7 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) } } while (!wilc->quit); - if (!ret) + if (ret) goto out_release_bus; timeout = 200; @@ -557,16 +557,16 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) WILC_VMM_TBL_RX_SHADOW_BASE, (u8 *)vmm_table, ((i + 1) * 4)); - if (!ret) + if (ret) break; ret = func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x2); - if (!ret) + if (ret) break; do { ret = func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, ®); - if (!ret) + if (ret) break; if ((reg >> 2) & 0x1) { entries = ((reg >> 3) & 0x3f); @@ -579,19 +579,19 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) break; } - if (!ret) + if (ret) break; if (entries == 0) { ret = func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®); - if (!ret) + if (ret) break; reg &= ~BIT(0); ret = func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, reg); } } while (0); - if (!ret) + if (ret) goto out_release_bus; if (entries == 0) { @@ -654,7 +654,7 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); ret = func->hif_clear_int_ext(wilc, ENABLE_TX_VMM); - if (!ret) + if (ret) goto out_release_bus; ret = func->hif_block_tx_ext(wilc, 0, txb, offset); @@ -771,7 +771,7 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) wilc->hif_func->hif_clear_int_ext(wilc, DATA_INT_CLR | ENABLE_RX_VMM); ret = wilc->hif_func->hif_block_rx_ext(wilc, 0, buffer, size); - if (!ret) + if (ret) return; offset += size; @@ -832,7 +832,7 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, memcpy(dma_buffer, &buffer[offset], size2); ret = wilc->hif_func->hif_block_tx(wilc, addr, dma_buffer, size2); - if (!ret) + if (ret) break; addr += size2; @@ -841,17 +841,15 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, } release_bus(wilc, WILC_BUS_RELEASE_ONLY); - if (!ret) { - ret = -EIO; + if (ret) goto fail; - } } while (offset < buffer_size); fail: kfree(dma_buffer); - return (ret < 0) ? ret : 0; + return ret; } int wilc_wlan_start(struct wilc *wilc) @@ -868,26 +866,26 @@ int wilc_wlan_start(struct wilc *wilc) } acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg); - if (!ret) { + if (ret) { release_bus(wilc, WILC_BUS_RELEASE_ONLY); - return -EIO; + return ret; } reg = 0; if (wilc->io_type == WILC_HIF_SDIO && wilc->dev_irq_num) reg |= WILC_HAVE_SDIO_IRQ_GPIO; ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg); - if (!ret) { + if (ret) { release_bus(wilc, WILC_BUS_RELEASE_ONLY); - return -EIO; + return ret; } wilc->hif_func->hif_sync_ext(wilc, NUM_INT_EXT); ret = wilc->hif_func->hif_read_reg(wilc, 0x1000, &chipid); - if (!ret) { + if (ret) { release_bus(wilc, WILC_BUS_RELEASE_ONLY); - return -EIO; + return ret; } wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); @@ -902,7 +900,7 @@ int wilc_wlan_start(struct wilc *wilc) wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); release_bus(wilc, WILC_BUS_RELEASE_ONLY); - return (ret < 0) ? ret : 0; + return ret; } int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) @@ -913,33 +911,33 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, ®); - if (!ret) { + if (ret) { netdev_err(vif->ndev, "Error while reading reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return -EIO; + return ret; } ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0, (reg | WILC_ABORT_REQ_BIT)); - if (!ret) { + if (ret) { netdev_err(vif->ndev, "Error while writing reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return -EIO; + return ret; } ret = wilc->hif_func->hif_read_reg(wilc, WILC_FW_HOST_COMM, ®); - if (!ret) { + if (ret) { netdev_err(vif->ndev, "Error while reading reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return -EIO; + return ret; } reg = BIT(0); ret = wilc->hif_func->hif_write_reg(wilc, WILC_FW_HOST_COMM, reg); - if (!ret) { + if (ret) { netdev_err(vif->ndev, "Error while writing reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return -EIO; + return ret; } release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); @@ -1112,10 +1110,11 @@ int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, return ret; } -static u32 init_chip(struct net_device *dev) +static int init_chip(struct net_device *dev) { u32 chipid; - u32 reg, ret = 0; + u32 reg; + int ret = 0; struct wilc_vif *vif = netdev_priv(dev); struct wilc *wilc = vif->wilc; @@ -1125,18 +1124,18 @@ static u32 init_chip(struct net_device *dev) if ((chipid & 0xfff) != 0xa0) { ret = wilc->hif_func->hif_read_reg(wilc, 0x1118, ®); - if (!ret) { + if (ret) { netdev_err(dev, "fail read reg 0x1118\n"); goto release; } reg |= BIT(0); ret = wilc->hif_func->hif_write_reg(wilc, 0x1118, reg); - if (!ret) { + if (ret) { netdev_err(dev, "fail write reg 0x1118\n"); goto release; } ret = wilc->hif_func->hif_write_reg(wilc, 0xc0000, 0x71); - if (!ret) { + if (ret) { netdev_err(dev, "fail write reg 0xc0000\n"); goto release; } @@ -1186,7 +1185,7 @@ int wilc_wlan_init(struct net_device *dev) wilc->quit = 0; - if (!wilc->hif_func->hif_init(wilc, false)) { + if (wilc->hif_func->hif_init(wilc, false)) { ret = -EIO; goto fail; } @@ -1207,12 +1206,12 @@ int wilc_wlan_init(struct net_device *dev) goto fail; } - if (!init_chip(dev)) { + if (init_chip(dev)) { ret = -EIO; goto fail; } - return 1; + return 0; fail: From bd4217cb9d54171a109fe63d0ac801cc7a18edb9 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 23 Jan 2020 12:50:49 +0000 Subject: [PATCH 344/353] staging: wilc1000: avoid mutex unlock without lock in wilc_wlan_handle_txq() In wilc_wlan_handle_txq(), mutex unlock was called without acquiring it. Also error code for full VMM condition was incorrect as discussed in [1]. Now used a proper code to indicate VMM is full, for which transfer to VMM is required again. 'wilc_wlan_handle_txq()' should be called again if the VMM space was full earlier or otherwise based on 'txq_event' signal. 1. https://lore.kernel.org/driverdev-devel/20191113183322.a54mh2w6dulklgsd@kili.mountain/ Signed-off-by: Ajay Singh Link: https://lore.kernel.org/r/20200123182129.4053-2-ajay.kathat@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/netdev.c | 2 +- drivers/staging/wilc1000/wlan.c | 15 ++++++++++----- drivers/staging/wilc1000/wlan.h | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/netdev.c b/drivers/staging/wilc1000/netdev.c index 0f48e74aa3ea..fce5bf2d82fa 100644 --- a/drivers/staging/wilc1000/netdev.c +++ b/drivers/staging/wilc1000/netdev.c @@ -174,7 +174,7 @@ static int wilc_txq_task(void *vp) } srcu_read_unlock(&wl->srcu, srcu_idx); } - } while (ret == -ENOBUFS && !wl->close); + } while (ret == WILC_VMM_ENTRY_FULL_RETRY && !wl->close); } return 0; } diff --git a/drivers/staging/wilc1000/wlan.c b/drivers/staging/wilc1000/wlan.c index b904eda42806..601e4d1345d2 100644 --- a/drivers/staging/wilc1000/wlan.c +++ b/drivers/staging/wilc1000/wlan.c @@ -489,12 +489,12 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) struct wilc_vif *vif; if (wilc->quit) - goto out; + goto out_update_cnt; mutex_lock(&wilc->txq_add_to_head_cs); tqe = wilc_wlan_txq_get_first(wilc); if (!tqe) - goto out; + goto out_unlock; dev = tqe->vif->ndev; wilc_wlan_txq_filter_dup_tcp_ack(dev); i = 0; @@ -526,7 +526,7 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) } if (i == 0) - goto out; + goto out_unlock; vmm_table[i] = 0x0; acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); @@ -595,7 +595,11 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) goto out_release_bus; if (entries == 0) { - ret = -ENOBUFS; + /* + * No VMM space available in firmware so retry to transmit + * the packet from tx queue. + */ + ret = WILC_VMM_ENTRY_FULL_RETRY; goto out_release_bus; } @@ -662,9 +666,10 @@ int wilc_wlan_handle_txq(struct wilc *wilc, u32 *txq_count) out_release_bus: release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); -out: +out_unlock: mutex_unlock(&wilc->txq_add_to_head_cs); +out_update_cnt: *txq_count = wilc->txq_entries; return ret; } diff --git a/drivers/staging/wilc1000/wlan.h b/drivers/staging/wilc1000/wlan.h index 44ae6ed6882c..8c4634262adb 100644 --- a/drivers/staging/wilc1000/wlan.h +++ b/drivers/staging/wilc1000/wlan.h @@ -198,6 +198,7 @@ #define IS_MGMT_STATUS_SUCCES 0x040 #define WILC_WID_TYPE GENMASK(15, 12) +#define WILC_VMM_ENTRY_FULL_RETRY 1 /******************************************** * * Tx/Rx Queue Structure From 52b0c4709d23ad018a6acf34ca194fa60c71814b Mon Sep 17 00:00:00 2001 From: Tetsuhiro Kohada Date: Thu, 23 Jan 2020 19:24:45 +0900 Subject: [PATCH 345/353] staging: exfat: remove fs_func struct. Remove 'fs_func struct' and change indirect calls to direct calls. The following issues are described in exfat's TODO. > Create helper function for exfat_set_entry_time () and > exfat_set_entry_type () because it's sort of ugly to be calling the same functionn directly and other code calling through the fs_func struc ponters ... The fs_func struct was used for switching the helper functions of fat16/fat32/exfat. Now, it has lost the role of switching, just making the code less readable. Signed-off-by: Tetsuhiro Kohada Link: https://lore.kernel.org/r/20200123102445.123033-1-Kohada.Tetsuhiro@dc.MitsubishiElectric.co.jp Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat.h | 79 +++++----- drivers/staging/exfat/exfat_core.c | 214 +++++++++++----------------- drivers/staging/exfat/exfat_super.c | 119 ++++++++-------- 3 files changed, 178 insertions(+), 234 deletions(-) diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h index 3865c17027ce..4d87360fab35 100644 --- a/drivers/staging/exfat/exfat.h +++ b/drivers/staging/exfat/exfat.h @@ -516,49 +516,6 @@ struct buf_cache_t { struct buffer_head *buf_bh; }; -struct fs_func { - s32 (*alloc_cluster)(struct super_block *sb, s32 num_alloc, - struct chain_t *p_chain); - void (*free_cluster)(struct super_block *sb, struct chain_t *p_chain, - s32 do_relse); - s32 (*count_used_clusters)(struct super_block *sb); - - s32 (*init_dir_entry)(struct super_block *sb, struct chain_t *p_dir, - s32 entry, u32 type, u32 start_clu, u64 size); - s32 (*init_ext_entry)(struct super_block *sb, struct chain_t *p_dir, - s32 entry, s32 num_entries, - struct uni_name_t *p_uniname, - struct dos_name_t *p_dosname); - s32 (*find_dir_entry)(struct super_block *sb, struct chain_t *p_dir, - struct uni_name_t *p_uniname, s32 num_entries, - struct dos_name_t *p_dosname, u32 type); - void (*delete_dir_entry)(struct super_block *sb, - struct chain_t *p_dir, s32 entry, - s32 offset, s32 num_entries); - void (*get_uni_name_from_ext_entry)(struct super_block *sb, - struct chain_t *p_dir, s32 entry, - u16 *uniname); - s32 (*count_ext_entries)(struct super_block *sb, - struct chain_t *p_dir, s32 entry, - struct dentry_t *p_entry); - s32 (*calc_num_entries)(struct uni_name_t *p_uniname); - - u32 (*get_entry_type)(struct dentry_t *p_entry); - void (*set_entry_type)(struct dentry_t *p_entry, u32 type); - u32 (*get_entry_attr)(struct dentry_t *p_entry); - void (*set_entry_attr)(struct dentry_t *p_entry, u32 attr); - u8 (*get_entry_flag)(struct dentry_t *p_entry); - void (*set_entry_flag)(struct dentry_t *p_entry, u8 flag); - u32 (*get_entry_clu0)(struct dentry_t *p_entry); - void (*set_entry_clu0)(struct dentry_t *p_entry, u32 clu0); - u64 (*get_entry_size)(struct dentry_t *p_entry); - void (*set_entry_size)(struct dentry_t *p_entry, u64 size); - void (*get_entry_time)(struct dentry_t *p_entry, - struct timestamp_t *tp, u8 mode); - void (*set_entry_time)(struct dentry_t *p_entry, - struct timestamp_t *tp, u8 mode); -}; - struct fs_info_t { u32 drv; /* drive ID */ u32 vol_type; /* volume FAT type */ @@ -597,7 +554,6 @@ struct fs_info_t { u32 dev_ejected; /* block device operation error flag */ - struct fs_func *fs_func; struct mutex v_mutex; /* FAT cache */ @@ -829,5 +785,40 @@ int exfat_bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh, u32 num_secs, bool sync); int exfat_bdev_sync(struct super_block *sb); +/* cluster operation functions */ +s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, + struct chain_t *p_chain); +void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, + s32 do_relse); +s32 exfat_count_used_clusters(struct super_block *sb); + +/* dir operation functions */ +s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 num_entries, + struct dos_name_t *p_dosname, u32 type); +void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 order, s32 num_entries); +void exfat_get_uni_name_from_ext_entry(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u16 *uniname); +s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, + s32 entry, struct dentry_t *p_entry); +s32 exfat_calc_num_entries(struct uni_name_t *p_uniname); + +/* dir entry getter/setter */ +u32 exfat_get_entry_type(struct dentry_t *p_entry); +u32 exfat_get_entry_attr(struct dentry_t *p_entry); +void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr); +u8 exfat_get_entry_flag(struct dentry_t *p_entry); +void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags); +u32 exfat_get_entry_clu0(struct dentry_t *p_entry); +void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu); +u64 exfat_get_entry_size(struct dentry_t *p_entry); +void exfat_set_entry_size(struct dentry_t *p_entry, u64 size); +void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode); +void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode); + extern const u8 uni_upcase[]; #endif /* _EXFAT_H */ diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c index 36a4102c057d..07b460d01334 100644 --- a/drivers/staging/exfat/exfat_core.c +++ b/drivers/staging/exfat/exfat_core.c @@ -249,8 +249,8 @@ static u32 test_alloc_bitmap(struct super_block *sb, u32 clu) return CLUSTER_32(~0); } -static s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, - struct chain_t *p_chain) +s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, + struct chain_t *p_chain) { s32 num_clusters = 0; u32 hint_clu, new_clu, last_clu = CLUSTER_32(~0); @@ -328,8 +328,8 @@ static s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, return num_clusters; } -static void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, - s32 do_relse) +void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, + s32 do_relse) { s32 num_clusters = 0; u32 clu; @@ -434,7 +434,7 @@ s32 count_num_clusters(struct super_block *sb, struct chain_t *p_chain) return count; } -static s32 exfat_count_used_clusters(struct super_block *sb) +s32 exfat_count_used_clusters(struct super_block *sb) { int i, map_i, map_b, count = 0; u8 k; @@ -499,7 +499,7 @@ s32 load_alloc_bitmap(struct super_block *sb) if (!ep) return -ENOENT; - type = p_fs->fs_func->get_entry_type((struct dentry_t *)ep); + type = exfat_get_entry_type((struct dentry_t *)ep); if (type == TYPE_UNUSED) break; @@ -745,7 +745,7 @@ s32 load_upcase_table(struct super_block *sb) if (!ep) return -ENOENT; - type = p_fs->fs_func->get_entry_type((struct dentry_t *)ep); + type = exfat_get_entry_type((struct dentry_t *)ep); if (type == TYPE_UNUSED) break; @@ -787,7 +787,7 @@ void free_upcase_table(struct super_block *sb) * Directory Entry Management Functions */ -static u32 exfat_get_entry_type(struct dentry_t *p_entry) +u32 exfat_get_entry_type(struct dentry_t *p_entry) { struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; @@ -862,56 +862,56 @@ static void exfat_set_entry_type(struct dentry_t *p_entry, u32 type) } } -static u32 exfat_get_entry_attr(struct dentry_t *p_entry) +u32 exfat_get_entry_attr(struct dentry_t *p_entry) { struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; return (u32)GET16_A(ep->attr); } -static void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr) +void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr) { struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; SET16_A(ep->attr, (u16)attr); } -static u8 exfat_get_entry_flag(struct dentry_t *p_entry) +u8 exfat_get_entry_flag(struct dentry_t *p_entry) { struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; return ep->flags; } -static void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags) +void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags) { struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; ep->flags = flags; } -static u32 exfat_get_entry_clu0(struct dentry_t *p_entry) +u32 exfat_get_entry_clu0(struct dentry_t *p_entry) { struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; return GET32_A(ep->start_clu); } -static void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu) +void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu) { struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; SET32_A(ep->start_clu, start_clu); } -static u64 exfat_get_entry_size(struct dentry_t *p_entry) +u64 exfat_get_entry_size(struct dentry_t *p_entry) { struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; return GET64_A(ep->valid_size); } -static void exfat_set_entry_size(struct dentry_t *p_entry, u64 size) +void exfat_set_entry_size(struct dentry_t *p_entry, u64 size) { struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; @@ -919,8 +919,8 @@ static void exfat_set_entry_size(struct dentry_t *p_entry, u64 size) SET64_A(ep->size, size); } -static void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, - u8 mode) +void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode) { u16 t = 0x00, d = 0x21; struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; @@ -948,8 +948,8 @@ static void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *t tp->year = (d >> 9); } -static void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, - u8 mode) +void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode) { u16 t, d; struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; @@ -1088,20 +1088,19 @@ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir, return 0; } -static void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, - s32 entry, s32 order, s32 num_entries) +void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 order, s32 num_entries) { int i; sector_t sector; struct dentry_t *ep; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); for (i = order; i < num_entries; i++) { ep = get_entry_in_dir(sb, p_dir, entry + i, §or); if (!ep) return; - p_fs->fs_func->set_entry_type(ep, TYPE_DELETED); + exfat_set_entry_type(ep, TYPE_DELETED); exfat_buf_modify(sb, sector); } } @@ -1366,7 +1365,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, goto err_out; ep = (struct dentry_t *)(buf + off); - entry_type = p_fs->fs_func->get_entry_type(ep); + entry_type = exfat_get_entry_type(ep); if ((entry_type != TYPE_FILE) && (entry_type != TYPE_DIR)) goto err_out; @@ -1396,7 +1395,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, * instead of copying whole sector, we will check every entry. * this will provide minimum stablity and consistency. */ - entry_type = p_fs->fs_func->get_entry_type(ep); + entry_type = exfat_get_entry_type(ep); if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) goto err_out; @@ -1540,7 +1539,7 @@ static s32 search_deleted_or_unused_entry(struct super_block *sb, if (!ep) return -1; - type = p_fs->fs_func->get_entry_type(ep); + type = exfat_get_entry_type(ep); if (type == TYPE_UNUSED) { num_empty++; @@ -1614,7 +1613,7 @@ static s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_ clu.flags = p_dir->flags; /* (1) allocate a cluster */ - ret = p_fs->fs_func->alloc_cluster(sb, 1, &clu); + ret = exfat_alloc_cluster(sb, 1, &clu); if (ret < 1) return -EIO; @@ -1650,8 +1649,8 @@ static s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_ fid->entry + 1, §or); if (!ep) return -ENOENT; - p_fs->fs_func->set_entry_size(ep, size); - p_fs->fs_func->set_entry_flag(ep, p_dir->flags); + exfat_set_entry_size(ep, size); + exfat_set_entry_flag(ep, p_dir->flags); exfat_buf_modify(sb, sector); update_dir_checksum(sb, &fid->dir, @@ -1690,9 +1689,9 @@ static s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *unina * -1 : (root dir, ".") it is the root dir itself * -2 : entry with the name does not exist */ -static s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, - struct uni_name_t *p_uniname, s32 num_entries, - struct dos_name_t *p_dosname, u32 type) +s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 num_entries, + struct dos_name_t *p_dosname, u32 type) { int i = 0, dentry = 0, num_ext_entries = 0, len, step; s32 order = 0; @@ -1736,7 +1735,7 @@ static s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, if (!ep) return -2; - entry_type = p_fs->fs_func->get_entry_type(ep); + entry_type = exfat_get_entry_type(ep); step = 1; if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) { @@ -1833,21 +1832,20 @@ static s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, return -2; } -static s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, - s32 entry, struct dentry_t *p_entry) +s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, + s32 entry, struct dentry_t *p_entry) { int i, count = 0; u32 type; struct file_dentry_t *file_ep = (struct file_dentry_t *)p_entry; struct dentry_t *ext_ep; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); for (i = 0, entry++; i < file_ep->num_ext; i++, entry++) { ext_ep = get_entry_in_dir(sb, p_dir, entry, NULL); if (!ext_ep) return -1; - type = p_fs->fs_func->get_entry_type(ext_ep); + type = exfat_get_entry_type(ext_ep); if ((type == TYPE_EXTEND) || (type == TYPE_STREAM)) count++; else @@ -1885,7 +1883,7 @@ s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir, if (!ep) return -ENOENT; - entry_type = p_fs->fs_func->get_entry_type(ep); + entry_type = exfat_get_entry_type(ep); if (entry_type == TYPE_UNUSED) return count; @@ -1941,7 +1939,7 @@ bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir) if (!ep) break; - type = p_fs->fs_func->get_entry_type(ep); + type = exfat_get_entry_type(ep); if (type == TYPE_UNUSED) return true; @@ -1985,9 +1983,8 @@ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir, struct dos_name_t *p_dosname) { s32 num_entries; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - num_entries = p_fs->fs_func->calc_num_entries(p_uniname); + num_entries = exfat_calc_num_entries(p_uniname); if (num_entries == 0) return -EINVAL; @@ -1996,14 +1993,13 @@ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir, return 0; } -static void exfat_get_uni_name_from_ext_entry(struct super_block *sb, - struct chain_t *p_dir, s32 entry, - u16 *uniname) +void exfat_get_uni_name_from_ext_entry(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u16 *uniname) { int i; struct dentry_t *ep; struct entry_set_cache_t *es; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); es = get_entry_set_in_dir(sb, p_dir, entry, ES_ALL_ENTRIES, &ep); if (!es || es->num_entries < 3) { @@ -2021,7 +2017,7 @@ static void exfat_get_uni_name_from_ext_entry(struct super_block *sb, * So, the index of first file-name dentry should start from 2. */ for (i = 2; i < es->num_entries; i++, ep++) { - if (p_fs->fs_func->get_entry_type(ep) == TYPE_EXTEND) + if (exfat_get_entry_type(ep) == TYPE_EXTEND) extract_uni_name_from_name_entry((struct name_dentry_t *) ep, uniname, i); else @@ -2033,7 +2029,7 @@ out: release_entry_set(es); } -static s32 exfat_calc_num_entries(struct uni_name_t *p_uniname) +s32 exfat_calc_num_entries(struct uni_name_t *p_uniname) { s32 len; @@ -2101,36 +2097,6 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir, return 0; } -/* - * File Operation Functions - */ -static struct fs_func exfat_fs_func = { - .alloc_cluster = exfat_alloc_cluster, - .free_cluster = exfat_free_cluster, - .count_used_clusters = exfat_count_used_clusters, - - .init_dir_entry = exfat_init_dir_entry, - .init_ext_entry = exfat_init_ext_entry, - .find_dir_entry = exfat_find_dir_entry, - .delete_dir_entry = exfat_delete_dir_entry, - .get_uni_name_from_ext_entry = exfat_get_uni_name_from_ext_entry, - .count_ext_entries = exfat_count_ext_entries, - .calc_num_entries = exfat_calc_num_entries, - - .get_entry_type = exfat_get_entry_type, - .set_entry_type = exfat_set_entry_type, - .get_entry_attr = exfat_get_entry_attr, - .set_entry_attr = exfat_set_entry_attr, - .get_entry_flag = exfat_get_entry_flag, - .set_entry_flag = exfat_set_entry_flag, - .get_entry_clu0 = exfat_get_entry_clu0, - .set_entry_clu0 = exfat_set_entry_clu0, - .get_entry_size = exfat_get_entry_size, - .set_entry_size = exfat_set_entry_size, - .get_entry_time = exfat_get_entry_time, - .set_entry_time = exfat_set_entry_time, -}; - s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr) { struct bpbex_t *p_bpb = (struct bpbex_t *)p_pbr->bpb; @@ -2174,8 +2140,6 @@ s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr) p_fs->clu_srch_ptr = 2; p_fs->used_clusters = UINT_MAX; - p_fs->fs_func = &exfat_fs_func; - return 0; } @@ -2188,7 +2152,6 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir, struct dos_name_t dos_name; struct super_block *sb = inode->i_sb; struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct fs_func *fs_func = p_fs->fs_func; ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, &dos_name); @@ -2205,7 +2168,7 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir, clu.flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; /* (1) allocate a cluster */ - ret = fs_func->alloc_cluster(sb, 1, &clu); + ret = exfat_alloc_cluster(sb, 1, &clu); if (ret < 0) return ret; else if (ret == 0) @@ -2219,13 +2182,13 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir, /* (2) update the directory entry */ /* make sub-dir entry in parent directory */ - ret = fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_DIR, clu.dir, - size); + ret = exfat_init_dir_entry(sb, p_dir, dentry, TYPE_DIR, clu.dir, + size); if (ret != 0) return ret; - ret = fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, - &dos_name); + ret = exfat_init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, + &dos_name); if (ret != 0) return ret; @@ -2253,7 +2216,6 @@ s32 create_file(struct inode *inode, struct chain_t *p_dir, struct dos_name_t dos_name; struct super_block *sb = inode->i_sb; struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct fs_func *fs_func = p_fs->fs_func; ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, &dos_name); @@ -2269,13 +2231,13 @@ s32 create_file(struct inode *inode, struct chain_t *p_dir, /* fill the dos name directory entry information of the created file. * the first cluster is not determined yet. (0) */ - ret = fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_FILE | mode, - CLUSTER_32(0), 0); + ret = exfat_init_dir_entry(sb, p_dir, dentry, TYPE_FILE | mode, + CLUSTER_32(0), 0); if (ret != 0) return ret; - ret = fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, - &dos_name); + ret = exfat_init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, + &dos_name); if (ret != 0) return ret; @@ -2302,8 +2264,6 @@ void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry) sector_t sector; struct dentry_t *ep; struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct fs_func *fs_func = p_fs->fs_func; ep = get_entry_in_dir(sb, p_dir, entry, §or); if (!ep) @@ -2312,7 +2272,7 @@ void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry) exfat_buf_lock(sb, sector); /* exfat_buf_lock() before call count_ext_entries() */ - num_entries = fs_func->count_ext_entries(sb, p_dir, entry, ep); + num_entries = exfat_count_ext_entries(sb, p_dir, entry, ep); if (num_entries < 0) { exfat_buf_unlock(sb, sector); return; @@ -2322,7 +2282,7 @@ void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry) exfat_buf_unlock(sb, sector); /* (1) update the directory entry */ - fs_func->delete_dir_entry(sb, p_dir, entry, 0, num_entries); + exfat_delete_dir_entry(sb, p_dir, entry, 0, num_entries); } s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry, @@ -2333,8 +2293,6 @@ s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry, struct dos_name_t dos_name; struct dentry_t *epold, *epnew; struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct fs_func *fs_func = p_fs->fs_func; epold = get_entry_in_dir(sb, p_dir, oldentry, §or_old); if (!epold) @@ -2343,8 +2301,8 @@ s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry, exfat_buf_lock(sb, sector_old); /* exfat_buf_lock() before call count_ext_entries() */ - num_old_entries = fs_func->count_ext_entries(sb, p_dir, oldentry, - epold); + num_old_entries = exfat_count_ext_entries(sb, p_dir, oldentry, + epold); if (num_old_entries < 0) { exfat_buf_unlock(sb, sector_old); return -ENOENT; @@ -2372,10 +2330,10 @@ s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry, } memcpy((void *)epnew, (void *)epold, DENTRY_SIZE); - if (fs_func->get_entry_type(epnew) == TYPE_FILE) { - fs_func->set_entry_attr(epnew, - fs_func->get_entry_attr(epnew) | - ATTR_ARCHIVE); + if (exfat_get_entry_type(epnew) == TYPE_FILE) { + exfat_set_entry_attr(epnew, + exfat_get_entry_attr(epnew) | + ATTR_ARCHIVE); fid->attr |= ATTR_ARCHIVE; } exfat_buf_modify(sb, sector_new); @@ -2396,33 +2354,33 @@ s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry, exfat_buf_modify(sb, sector_new); exfat_buf_unlock(sb, sector_old); - ret = fs_func->init_ext_entry(sb, p_dir, newentry, - num_new_entries, p_uniname, - &dos_name); + ret = exfat_init_ext_entry(sb, p_dir, newentry, + num_new_entries, p_uniname, + &dos_name); if (ret != 0) return ret; - fs_func->delete_dir_entry(sb, p_dir, oldentry, 0, - num_old_entries); + exfat_delete_dir_entry(sb, p_dir, oldentry, 0, + num_old_entries); fid->entry = newentry; } else { - if (fs_func->get_entry_type(epold) == TYPE_FILE) { - fs_func->set_entry_attr(epold, - fs_func->get_entry_attr(epold) | - ATTR_ARCHIVE); + if (exfat_get_entry_type(epold) == TYPE_FILE) { + exfat_set_entry_attr(epold, + exfat_get_entry_attr(epold) | + ATTR_ARCHIVE); fid->attr |= ATTR_ARCHIVE; } exfat_buf_modify(sb, sector_old); exfat_buf_unlock(sb, sector_old); - ret = fs_func->init_ext_entry(sb, p_dir, oldentry, - num_new_entries, p_uniname, - &dos_name); + ret = exfat_init_ext_entry(sb, p_dir, oldentry, + num_new_entries, p_uniname, + &dos_name); if (ret != 0) return ret; - fs_func->delete_dir_entry(sb, p_dir, oldentry, num_new_entries, - num_old_entries); + exfat_delete_dir_entry(sb, p_dir, oldentry, num_new_entries, + num_old_entries); } return 0; @@ -2437,23 +2395,21 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry, struct dos_name_t dos_name; struct dentry_t *epmov, *epnew; struct super_block *sb = inode->i_sb; - struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct fs_func *fs_func = p_fs->fs_func; epmov = get_entry_in_dir(sb, p_olddir, oldentry, §or_mov); if (!epmov) return -ENOENT; /* check if the source and target directory is the same */ - if (fs_func->get_entry_type(epmov) == TYPE_DIR && - fs_func->get_entry_clu0(epmov) == p_newdir->dir) + if (exfat_get_entry_type(epmov) == TYPE_DIR && + exfat_get_entry_clu0(epmov) == p_newdir->dir) return -EINVAL; exfat_buf_lock(sb, sector_mov); /* exfat_buf_lock() before call count_ext_entries() */ - num_old_entries = fs_func->count_ext_entries(sb, p_olddir, oldentry, - epmov); + num_old_entries = exfat_count_ext_entries(sb, p_olddir, oldentry, + epmov); if (num_old_entries < 0) { exfat_buf_unlock(sb, sector_mov); return -ENOENT; @@ -2480,9 +2436,9 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry, } memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE); - if (fs_func->get_entry_type(epnew) == TYPE_FILE) { - fs_func->set_entry_attr(epnew, fs_func->get_entry_attr(epnew) | - ATTR_ARCHIVE); + if (exfat_get_entry_type(epnew) == TYPE_FILE) { + exfat_set_entry_attr(epnew, exfat_get_entry_attr(epnew) | + ATTR_ARCHIVE); fid->attr |= ATTR_ARCHIVE; } exfat_buf_modify(sb, sector_new); @@ -2502,12 +2458,12 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry, exfat_buf_modify(sb, sector_new); exfat_buf_unlock(sb, sector_mov); - ret = fs_func->init_ext_entry(sb, p_newdir, newentry, num_new_entries, - p_uniname, &dos_name); + ret = exfat_init_ext_entry(sb, p_newdir, newentry, num_new_entries, + p_uniname, &dos_name); if (ret != 0) return ret; - fs_func->delete_dir_entry(sb, p_olddir, oldentry, 0, num_old_entries); + exfat_delete_dir_entry(sb, p_olddir, oldentry, 0, num_old_entries); fid->dir.dir = p_newdir->dir; fid->dir.size = p_newdir->size; diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 128ca4403d03..b81d2a87b82e 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -492,7 +492,7 @@ static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info) mutex_lock(&p_fs->v_mutex); if (p_fs->used_clusters == UINT_MAX) - p_fs->used_clusters = p_fs->fs_func->count_used_clusters(sb); + p_fs->used_clusters = exfat_count_used_clusters(sb); info->FatType = p_fs->vol_type; info->ClusterSize = p_fs->cluster_size; @@ -565,8 +565,8 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid) goto out; /* search the file name for directories */ - dentry = p_fs->fs_func->find_dir_entry(sb, &dir, &uni_name, num_entries, - &dos_name, TYPE_ALL); + dentry = exfat_find_dir_entry(sb, &dir, &uni_name, num_entries, + &dos_name, TYPE_ALL); if (dentry < -1) { ret = -ENOENT; goto out; @@ -595,18 +595,18 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid) } ep2 = ep + 1; - fid->type = p_fs->fs_func->get_entry_type(ep); + fid->type = exfat_get_entry_type(ep); fid->rwoffset = 0; fid->hint_last_off = -1; - fid->attr = p_fs->fs_func->get_entry_attr(ep); + fid->attr = exfat_get_entry_attr(ep); - fid->size = p_fs->fs_func->get_entry_size(ep2); + fid->size = exfat_get_entry_size(ep2); if ((fid->type == TYPE_FILE) && (fid->size == 0)) { fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; fid->start_clu = CLUSTER_32(~0); } else { - fid->flags = p_fs->fs_func->get_entry_flag(ep2); - fid->start_clu = p_fs->fs_func->get_entry_clu0(ep2); + fid->flags = exfat_get_entry_flag(ep2); + fid->start_clu = exfat_get_entry_clu0(ep2); } release_entry_set(es); @@ -886,9 +886,9 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, new_clu.flags = fid->flags; /* (1) allocate a chain of clusters */ - num_alloced = p_fs->fs_func->alloc_cluster(sb, - num_alloc, - &new_clu); + num_alloced = exfat_alloc_cluster(sb, + num_alloc, + &new_clu); if (num_alloced == 0) break; if (num_alloced < 0) { @@ -991,18 +991,18 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, goto err_out; ep2 = ep + 1; - p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY); - p_fs->fs_func->set_entry_attr(ep, fid->attr); + exfat_set_entry_time(ep, tm_current(&tm), TM_MODIFY); + exfat_set_entry_attr(ep, fid->attr); if (modified) { - if (p_fs->fs_func->get_entry_flag(ep2) != fid->flags) - p_fs->fs_func->set_entry_flag(ep2, fid->flags); + if (exfat_get_entry_flag(ep2) != fid->flags) + exfat_set_entry_flag(ep2, fid->flags); - if (p_fs->fs_func->get_entry_size(ep2) != fid->size) - p_fs->fs_func->set_entry_size(ep2, fid->size); + if (exfat_get_entry_size(ep2) != fid->size) + exfat_set_entry_size(ep2, fid->size); - if (p_fs->fs_func->get_entry_clu0(ep2) != fid->start_clu) - p_fs->fs_func->set_entry_clu0(ep2, fid->start_clu); + if (exfat_get_entry_clu0(ep2) != fid->start_clu) + exfat_set_entry_clu0(ep2, fid->start_clu); } update_dir_checksum_with_entry_set(sb, es); @@ -1108,13 +1108,13 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) } ep2 = ep + 1; - p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY); - p_fs->fs_func->set_entry_attr(ep, fid->attr); + exfat_set_entry_time(ep, tm_current(&tm), TM_MODIFY); + exfat_set_entry_attr(ep, fid->attr); - p_fs->fs_func->set_entry_size(ep2, new_size); + exfat_set_entry_size(ep2, new_size); if (new_size == 0) { - p_fs->fs_func->set_entry_flag(ep2, 0x01); - p_fs->fs_func->set_entry_clu0(ep2, CLUSTER_32(0)); + exfat_set_entry_flag(ep2, 0x01); + exfat_set_entry_clu0(ep2, CLUSTER_32(0)); } update_dir_checksum_with_entry_set(sb, es); @@ -1127,7 +1127,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) } /* (3) free the clusters */ - p_fs->fs_func->free_cluster(sb, &clu, 0); + exfat_free_cluster(sb, &clu, 0); /* hint information */ fid->hint_last_off = -1; @@ -1217,7 +1217,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, goto out2; } - if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) { + if (exfat_get_entry_attr(ep) & ATTR_READONLY) { ret = -EPERM; goto out2; } @@ -1237,7 +1237,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, if (!ep) goto out; - entry_type = p_fs->fs_func->get_entry_type(ep); + entry_type = exfat_get_entry_type(ep); if (entry_type == TYPE_DIR) { struct chain_t new_clu; @@ -1274,12 +1274,12 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, if (!ep) goto out; - num_entries = p_fs->fs_func->count_ext_entries(sb, p_dir, - new_entry, ep); + num_entries = exfat_count_ext_entries(sb, p_dir, + new_entry, ep); if (num_entries < 0) goto out; - p_fs->fs_func->delete_dir_entry(sb, p_dir, new_entry, 0, - num_entries + 1); + exfat_delete_dir_entry(sb, p_dir, new_entry, 0, + num_entries + 1); } out: #ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC @@ -1324,7 +1324,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid) goto out; } - if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) { + if (exfat_get_entry_attr(ep) & ATTR_READONLY) { ret = -EPERM; goto out; } @@ -1338,7 +1338,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid) clu_to_free.flags = fid->flags; /* (2) free the clusters */ - p_fs->fs_func->free_cluster(sb, &clu_to_free, 0); + exfat_free_cluster(sb, &clu_to_free, 0); fid->size = 0; fid->start_clu = CLUSTER_32(~0); @@ -1398,7 +1398,7 @@ static int ffsSetAttr(struct inode *inode, u32 attr) goto out; } - type = p_fs->fs_func->get_entry_type(ep); + type = exfat_get_entry_type(ep); if (((type == TYPE_FILE) && (attr & ATTR_SUBDIR)) || ((type == TYPE_DIR) && (!(attr & ATTR_SUBDIR)))) { @@ -1415,7 +1415,7 @@ static int ffsSetAttr(struct inode *inode, u32 attr) /* set the file attribute */ fid->attr = attr; - p_fs->fs_func->set_entry_attr(ep, attr); + exfat_set_entry_attr(ep, attr); update_dir_checksum_with_entry_set(sb, es); release_entry_set(es); @@ -1502,9 +1502,9 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) ep2 = ep + 1; /* set FILE_INFO structure using the acquired struct dentry_t */ - info->Attr = p_fs->fs_func->get_entry_attr(ep); + info->Attr = exfat_get_entry_attr(ep); - p_fs->fs_func->get_entry_time(ep, &tm, TM_CREATE); + exfat_get_entry_time(ep, &tm, TM_CREATE); info->CreateTimestamp.Year = tm.year; info->CreateTimestamp.Month = tm.mon; info->CreateTimestamp.Day = tm.day; @@ -1513,7 +1513,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) info->CreateTimestamp.Second = tm.sec; info->CreateTimestamp.MilliSecond = 0; - p_fs->fs_func->get_entry_time(ep, &tm, TM_MODIFY); + exfat_get_entry_time(ep, &tm, TM_MODIFY); info->ModifyTimestamp.Year = tm.year; info->ModifyTimestamp.Month = tm.mon; info->ModifyTimestamp.Day = tm.day; @@ -1528,13 +1528,13 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) /* XXX this is very bad for exfat cuz name is already included in es. * API should be revised */ - p_fs->fs_func->get_uni_name_from_ext_entry(sb, &fid->dir, fid->entry, - uni_name.name); + exfat_get_uni_name_from_ext_entry(sb, &fid->dir, fid->entry, + uni_name.name); nls_uniname_to_cstring(sb, info->Name, &uni_name); info->NumSubdirs = 2; - info->Size = p_fs->fs_func->get_entry_size(ep2); + info->Size = exfat_get_entry_size(ep2); release_entry_set(es); @@ -1602,7 +1602,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info) } ep2 = ep + 1; - p_fs->fs_func->set_entry_attr(ep, info->Attr); + exfat_set_entry_attr(ep, info->Attr); /* set FILE_INFO structure using the acquired struct dentry_t */ tm.sec = info->CreateTimestamp.Second; @@ -1611,7 +1611,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info) tm.day = info->CreateTimestamp.Day; tm.mon = info->CreateTimestamp.Month; tm.year = info->CreateTimestamp.Year; - p_fs->fs_func->set_entry_time(ep, &tm, TM_CREATE); + exfat_set_entry_time(ep, &tm, TM_CREATE); tm.sec = info->ModifyTimestamp.Second; tm.min = info->ModifyTimestamp.Minute; @@ -1619,9 +1619,9 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info) tm.day = info->ModifyTimestamp.Day; tm.mon = info->ModifyTimestamp.Month; tm.year = info->ModifyTimestamp.Year; - p_fs->fs_func->set_entry_time(ep, &tm, TM_MODIFY); + exfat_set_entry_time(ep, &tm, TM_MODIFY); - p_fs->fs_func->set_entry_size(ep2, info->Size); + exfat_set_entry_size(ep2, info->Size); update_dir_checksum_with_entry_set(sb, es); release_entry_set(es); @@ -1704,7 +1704,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) new_clu.flags = fid->flags; /* (1) allocate a cluster */ - num_alloced = p_fs->fs_func->alloc_cluster(sb, 1, &new_clu); + num_alloced = exfat_alloc_cluster(sb, 1, &new_clu); if (num_alloced < 0) { ret = -EIO; goto out; @@ -1744,13 +1744,11 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) /* (3) update directory entry */ if (modified) { - if (p_fs->fs_func->get_entry_flag(ep) != fid->flags) - p_fs->fs_func->set_entry_flag(ep, fid->flags); - - if (p_fs->fs_func->get_entry_clu0(ep) != fid->start_clu) - p_fs->fs_func->set_entry_clu0(ep, - fid->start_clu); + if (exfat_get_entry_flag(ep) != fid->flags) + exfat_set_entry_flag(ep, fid->flags); + if (exfat_get_entry_clu0(ep) != fid->start_clu) + exfat_set_entry_clu0(ep, fid->start_clu); } update_dir_checksum_with_entry_set(sb, es); @@ -1831,7 +1829,6 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) struct dentry_t *ep; struct super_block *sb = inode->i_sb; struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - struct fs_func *fs_func = p_fs->fs_func; struct file_id_t *fid = &(EXFAT_I(inode)->fid); /* check the validity of pointer parameters */ @@ -1913,7 +1910,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) ret = -ENOENT; goto out; } - type = fs_func->get_entry_type(ep); + type = exfat_get_entry_type(ep); if (type == TYPE_UNUSED) break; @@ -1922,9 +1919,9 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) continue; exfat_buf_lock(sb, sector); - dir_entry->Attr = fs_func->get_entry_attr(ep); + dir_entry->Attr = exfat_get_entry_attr(ep); - fs_func->get_entry_time(ep, &tm, TM_CREATE); + exfat_get_entry_time(ep, &tm, TM_CREATE); dir_entry->CreateTimestamp.Year = tm.year; dir_entry->CreateTimestamp.Month = tm.mon; dir_entry->CreateTimestamp.Day = tm.day; @@ -1933,7 +1930,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) dir_entry->CreateTimestamp.Second = tm.sec; dir_entry->CreateTimestamp.MilliSecond = 0; - fs_func->get_entry_time(ep, &tm, TM_MODIFY); + exfat_get_entry_time(ep, &tm, TM_MODIFY); dir_entry->ModifyTimestamp.Year = tm.year; dir_entry->ModifyTimestamp.Month = tm.mon; dir_entry->ModifyTimestamp.Day = tm.day; @@ -1946,8 +1943,8 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) sizeof(struct date_time_t)); *uni_name.name = 0x0; - fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry, - uni_name.name); + exfat_get_uni_name_from_ext_entry(sb, &dir, dentry, + uni_name.name); nls_uniname_to_cstring(sb, dir_entry->Name, &uni_name); exfat_buf_unlock(sb, sector); @@ -1957,7 +1954,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) goto out; } - dir_entry->Size = fs_func->get_entry_size(ep); + dir_entry->Size = exfat_get_entry_size(ep); /* hint information */ if (dir.dir == CLUSTER_32(0)) { /* FAT16 root_dir */ @@ -2047,7 +2044,7 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid) remove_file(inode, &dir, dentry); /* (2) free the clusters */ - p_fs->fs_func->free_cluster(sb, &clu_to_free, 1); + exfat_free_cluster(sb, &clu_to_free, 1); fid->size = 0; fid->start_clu = CLUSTER_32(~0); From 2893c678321904722dd588d91efa074e24828c6f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 23 Jan 2020 01:03:44 +0000 Subject: [PATCH 346/353] staging: comedi: drivers: fix spelling mistake "to" -> "too" There is a spelling mistake in a deb_dbg message. Fix it. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200123010344.2834618-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das6402.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index f99211ec46de..04e224f8b779 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -279,7 +279,7 @@ static int das6402_ai_check_chanlist(struct comedi_device *dev, if (aref0 == AREF_DIFF && chan > (s->n_chan / 2)) { dev_dbg(dev->class_dev, - "chanlist differential channel to large\n"); + "chanlist differential channel too large\n"); return -EINVAL; } } From 723de0f9171eeb49a3ae98cae82ebbbb992b3a7c Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Thu, 23 Jan 2020 16:38:17 +0100 Subject: [PATCH 347/353] staging: most: remove device from interface structure This patch makes the adapter drivers use their own device structures when registering a most interface with the core module. With this the module that actually operates the physical device is the owner of the device. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1579793906-5054-2-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 45 ++++++++++++++------------------ drivers/staging/most/dim2/dim2.c | 2 +- drivers/staging/most/most.h | 4 +-- drivers/staging/most/usb/usb.c | 20 +++++++++++--- 4 files changed, 38 insertions(+), 33 deletions(-) diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index bcad2525d94b..d0fe873ce67a 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -402,7 +402,7 @@ static ssize_t description_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_interface *iface = to_most_interface(dev); + struct most_interface *iface = dev_get_drvdata(dev); return snprintf(buf, PAGE_SIZE, "%s\n", iface->description); } @@ -411,7 +411,7 @@ static ssize_t interface_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct most_interface *iface = to_most_interface(dev); + struct most_interface *iface = dev_get_drvdata(dev); switch (iface->interface) { case ITYPE_LOOPBACK: @@ -476,7 +476,7 @@ static int print_links(struct device *dev, void *data) int offs = d->offs; char *buf = d->buf; struct most_channel *c; - struct most_interface *iface = to_most_interface(dev); + struct most_interface *iface = dev_get_drvdata(dev); list_for_each_entry(c, &iface->p->channel_list, list) { if (c->pipe0.comp) { @@ -484,7 +484,7 @@ static int print_links(struct device *dev, void *data) PAGE_SIZE - offs, "%s:%s:%s\n", c->pipe0.comp->name, - dev_name(&iface->dev), + dev_name(iface->dev), dev_name(&c->dev)); } if (c->pipe1.comp) { @@ -492,7 +492,7 @@ static int print_links(struct device *dev, void *data) PAGE_SIZE - offs, "%s:%s:%s\n", c->pipe1.comp->name, - dev_name(&iface->dev), + dev_name(iface->dev), dev_name(&c->dev)); } } @@ -534,7 +534,7 @@ static struct most_channel *get_channel(char *mdev, char *mdev_ch) dev = bus_find_device_by_name(&mc.bus, NULL, mdev); if (!dev) return NULL; - iface = to_most_interface(dev); + iface = dev_get_drvdata(dev); list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { if (!strcmp(dev_name(&c->dev), mdev_ch)) return c; @@ -1232,7 +1232,7 @@ static int disconnect_channels(struct device *dev, void *data) struct most_channel *c, *tmp; struct most_component *comp = data; - iface = to_most_interface(dev); + iface = dev_get_drvdata(dev); list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { if (c->pipe0.comp == comp || c->pipe1.comp == comp) comp->disconnect_channel(c->iface, c->channel_id); @@ -1261,14 +1261,11 @@ int most_deregister_component(struct most_component *comp) } EXPORT_SYMBOL_GPL(most_deregister_component); -static void release_interface(struct device *dev) -{ - dev_info(&mc.dev, "releasing interface dev %s...\n", dev_name(dev)); -} - static void release_channel(struct device *dev) { - dev_info(&mc.dev, "releasing channel dev %s...\n", dev_name(dev)); + struct most_channel *c = to_channel(dev); + + kfree(c); } /** @@ -1305,14 +1302,14 @@ int most_register_interface(struct most_interface *iface) INIT_LIST_HEAD(&iface->p->channel_list); iface->p->dev_id = id; strscpy(iface->p->name, iface->description, sizeof(iface->p->name)); - iface->dev.init_name = iface->p->name; - iface->dev.bus = &mc.bus; - iface->dev.parent = &mc.dev; - iface->dev.groups = interface_attr_groups; - iface->dev.release = release_interface; - if (device_register(&iface->dev)) { + iface->dev->bus = &mc.bus; + iface->dev->parent = &mc.dev; + iface->dev->groups = interface_attr_groups; + dev_set_drvdata(iface->dev, iface); + if (device_register(iface->dev)) { dev_err(&mc.dev, "registering iface->dev failed\n"); kfree(iface->p); + put_device(iface->dev); ida_simple_remove(&mdev_id, id); return -ENOMEM; } @@ -1328,7 +1325,7 @@ int most_register_interface(struct most_interface *iface) else snprintf(c->name, STRING_SIZE, "%s", name_suffix); c->dev.init_name = c->name; - c->dev.parent = &iface->dev; + c->dev.parent = iface->dev; c->dev.groups = channel_attr_groups; c->dev.release = release_channel; iface->p->channel[i] = c; @@ -1362,16 +1359,15 @@ int most_register_interface(struct most_interface *iface) return 0; err_free_most_channel: - kfree(c); + put_device(&c->dev); err_free_resources: while (i > 0) { c = iface->p->channel[--i]; device_unregister(&c->dev); - kfree(c); } kfree(iface->p); - device_unregister(&iface->dev); + device_unregister(iface->dev); ida_simple_remove(&mdev_id, id); return -ENOMEM; } @@ -1401,12 +1397,11 @@ void most_deregister_interface(struct most_interface *iface) c->pipe1.comp = NULL; list_del(&c->list); device_unregister(&c->dev); - kfree(c); } ida_simple_remove(&mdev_id, iface->p->dev_id); kfree(iface->p); - device_unregister(&iface->dev); + device_unregister(iface->dev); } EXPORT_SYMBOL_GPL(most_deregister_interface); diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index 15c6aa8fa1ea..fb704be6f4f8 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -854,8 +854,8 @@ static int dim2_probe(struct platform_device *pdev) dev->most_iface.poison_channel = poison_channel; dev->most_iface.request_netinfo = request_netinfo; dev->most_iface.driver_dev = &pdev->dev; + dev->most_iface.dev = &dev->dev; dev->dev.init_name = "dim2_state"; - dev->dev.parent = &dev->most_iface.dev; ret = most_register_interface(&dev->most_iface); if (ret) { diff --git a/drivers/staging/most/most.h b/drivers/staging/most/most.h index d93c6cea3a17..232e01b7f5d2 100644 --- a/drivers/staging/most/most.h +++ b/drivers/staging/most/most.h @@ -229,7 +229,7 @@ struct mbo { * @priv Private field used by mostcore to store context information. */ struct most_interface { - struct device dev; + struct device *dev; struct device *driver_dev; struct module *mod; enum most_interface_type interface; @@ -251,8 +251,6 @@ struct most_interface { struct interface_private *p; }; -#define to_most_interface(d) container_of(d, struct most_interface, dev) - /** * struct most_component - identifies a loadable component for the mostcore * @list: list_head diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c index 35217ca65cbb..dcc78cd870b8 100644 --- a/drivers/staging/most/usb/usb.c +++ b/drivers/staging/most/usb/usb.c @@ -102,6 +102,7 @@ struct clear_hold_work { * @poll_work_obj: work for polling link status */ struct most_dev { + struct device dev; struct usb_device *usb_device; struct most_interface iface; struct most_channel_capability *cap; @@ -123,6 +124,7 @@ struct most_dev { }; #define to_mdev(d) container_of(d, struct most_dev, iface) +#define to_mdev_from_dev(d) container_of(d, struct most_dev, dev) #define to_mdev_from_work(w) container_of(w, struct most_dev, poll_work_obj) static void wq_clear_halt(struct work_struct *wq_obj); @@ -1023,6 +1025,12 @@ static void release_dci(struct device *dev) kfree(dci); } +static void release_mdev(struct device *dev) +{ + struct most_dev *mdev = to_mdev_from_dev(dev); + + kfree(mdev); +} /** * hdm_probe - probe function of USB device driver * @interface: Interface of the attached USB device @@ -1061,6 +1069,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) mdev->link_stat_timer.expires = jiffies + (2 * HZ); mdev->iface.mod = hdm_usb_fops.owner; + mdev->iface.dev = &mdev->dev; mdev->iface.driver_dev = &interface->dev; mdev->iface.interface = ITYPE_USB; mdev->iface.configure = hdm_configure_channel; @@ -1079,6 +1088,9 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) usb_dev->config->desc.bConfigurationValue, usb_iface_desc->desc.bInterfaceNumber); + mdev->dev.init_name = mdev->description; + mdev->dev.parent = &interface->dev; + mdev->dev.release = release_mdev; mdev->conf = kcalloc(num_endpoints, sizeof(*mdev->conf), GFP_KERNEL); if (!mdev->conf) goto err_free_mdev; @@ -1152,7 +1164,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) } mdev->dci->dev.init_name = "dci"; - mdev->dci->dev.parent = &mdev->iface.dev; + mdev->dci->dev.parent = get_device(mdev->iface.dev); mdev->dci->dev.groups = dci_attr_groups; mdev->dci->dev.release = release_dci; if (device_register(&mdev->dci->dev)) { @@ -1166,7 +1178,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) mutex_unlock(&mdev->io_mutex); return 0; err_free_dci: - kfree(mdev->dci); + put_device(&mdev->dci->dev); err_free_busy_urbs: kfree(mdev->busy_urbs); err_free_ep_address: @@ -1176,7 +1188,7 @@ err_free_cap: err_free_conf: kfree(mdev->conf); err_free_mdev: - kfree(mdev); + put_device(&mdev->dev); err_out_of_memory: if (ret == 0 || ret == -ENOMEM) { ret = -ENOMEM; @@ -1213,7 +1225,7 @@ static void hdm_disconnect(struct usb_interface *interface) kfree(mdev->cap); kfree(mdev->conf); kfree(mdev->ep_address); - kfree(mdev); + put_device(&mdev->dev); } static struct usb_driver hdm_usb = { From 2485055394be272d098ca7dd63193d5041fb8140 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Thu, 23 Jan 2020 16:38:18 +0100 Subject: [PATCH 348/353] staging: most: core: drop device reference This patch drops the device reference added by function bus_find_device_by_name. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1579793906-5054-3-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index d0fe873ce67a..da79076e03d4 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -534,6 +534,7 @@ static struct most_channel *get_channel(char *mdev, char *mdev_ch) dev = bus_find_device_by_name(&mc.bus, NULL, mdev); if (!dev) return NULL; + put_device(dev); iface = dev_get_drvdata(dev); list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { if (!strcmp(dev_name(&c->dev), mdev_ch)) From 6a82c7758129441e7450703e6887d6cde003ff85 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Thu, 23 Jan 2020 16:38:19 +0100 Subject: [PATCH 349/353] staging: most: remove struct device core driver This patch removes the device from the MOST core driver and uses the device from the adapter driver. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1579793906-5054-4-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 52 +++++++++++--------------------- drivers/staging/most/dim2/dim2.c | 1 + 2 files changed, 19 insertions(+), 34 deletions(-) diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index da79076e03d4..37ee00bb8d53 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -30,7 +30,6 @@ static struct ida mdev_id; static int dummy_num_buffers; static struct mostcore { - struct device dev; struct device_driver drv; struct bus_type bus; struct list_head comp_list; @@ -151,7 +150,7 @@ static void flush_channel_fifos(struct most_channel *c) spin_unlock_irqrestore(&c->fifo_lock, hf_flags); if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo)))) - dev_warn(&mc.dev, "fifo | trash fifo not empty\n"); + dev_warn(&c->dev, "fifo | trash fifo not empty\n"); } /** @@ -624,7 +623,7 @@ int most_set_cfg_datatype(char *mdev, char *mdev_ch, char *buf) } if (i == ARRAY_SIZE(ch_data_type)) - dev_warn(&mc.dev, "invalid attribute settings\n"); + dev_warn(&c->dev, "invalid attribute settings\n"); return 0; } @@ -643,7 +642,7 @@ int most_set_cfg_direction(char *mdev, char *mdev_ch, char *buf) } else if (!strcmp(buf, "tx")) { c->cfg.direction = MOST_CH_TX; } else { - dev_err(&mc.dev, "Invalid direction\n"); + dev_err(&c->dev, "Invalid direction\n"); return -ENODATA; } return 0; @@ -796,7 +795,7 @@ static int hdm_enqueue_thread(void *data) mutex_unlock(&c->nq_mutex); if (unlikely(ret)) { - dev_err(&mc.dev, "hdm enqueue failed\n"); + dev_err(&c->dev, "hdm enqueue failed\n"); nq_hdm_mbo(mbo); c->hdm_enqueue_task = NULL; return 0; @@ -943,7 +942,7 @@ static void most_write_completion(struct mbo *mbo) c = mbo->context; if (mbo->status == MBO_E_INVAL) - dev_warn(&mc.dev, "Tx MBO status: invalid\n"); + dev_warn(&c->dev, "Tx MBO status: invalid\n"); if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) trash_mbo(mbo); else @@ -1102,14 +1101,14 @@ int most_start_channel(struct most_interface *iface, int id, goto out; /* already started by another component */ if (!try_module_get(iface->mod)) { - dev_err(&mc.dev, "failed to acquire HDM lock\n"); + dev_err(&c->dev, "failed to acquire HDM lock\n"); mutex_unlock(&c->start_mutex); return -ENOLCK; } c->cfg.extra_len = 0; if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) { - dev_err(&mc.dev, "channel configuration failed. Go check settings...\n"); + dev_err(&c->dev, "channel configuration failed. Go check settings...\n"); ret = -EINVAL; goto err_put_module; } @@ -1163,7 +1162,7 @@ int most_stop_channel(struct most_interface *iface, int id, struct most_channel *c; if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) { - dev_err(&mc.dev, "Bad interface or index out of range\n"); + pr_err("Bad interface or index out of range\n"); return -EINVAL; } c = iface->p->channel[id]; @@ -1183,7 +1182,7 @@ int most_stop_channel(struct most_interface *iface, int id, c->is_poisoned = true; if (c->iface->poison_channel(c->iface, c->channel_id)) { - dev_err(&mc.dev, "Cannot stop channel %d of mdev %s\n", c->channel_id, + dev_err(&c->dev, "Cannot stop channel %d of mdev %s\n", c->channel_id, c->iface->description); mutex_unlock(&c->start_mutex); return -EAGAIN; @@ -1193,7 +1192,7 @@ int most_stop_channel(struct most_interface *iface, int id, #ifdef CMPL_INTERRUPTIBLE if (wait_for_completion_interruptible(&c->cleanup)) { - dev_err(&mc.dev, "Interrupted while clean up ch %d\n", c->channel_id); + dev_err(&c->dev, "Interrupted while clean up ch %d\n", c->channel_id); mutex_unlock(&c->start_mutex); return -EINTR; } @@ -1219,7 +1218,7 @@ EXPORT_SYMBOL_GPL(most_stop_channel); int most_register_component(struct most_component *comp) { if (!comp) { - dev_err(&mc.dev, "Bad component\n"); + pr_err("Bad component\n"); return -EINVAL; } list_add_tail(&comp->list, &mc.comp_list); @@ -1252,7 +1251,7 @@ static int disconnect_channels(struct device *dev, void *data) int most_deregister_component(struct most_component *comp) { if (!comp) { - dev_err(&mc.dev, "Bad component\n"); + pr_err("Bad component\n"); return -EINVAL; } @@ -1284,13 +1283,13 @@ int most_register_interface(struct most_interface *iface) if (!iface || !iface->enqueue || !iface->configure || !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) { - dev_err(&mc.dev, "Bad interface or channel overflow\n"); + dev_err(iface->dev, "Bad interface or channel overflow\n"); return -EINVAL; } id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL); if (id < 0) { - dev_err(&mc.dev, "Failed to alloc mdev ID\n"); + dev_err(iface->dev, "Failed to alloc mdev ID\n"); return id; } @@ -1304,11 +1303,10 @@ int most_register_interface(struct most_interface *iface) iface->p->dev_id = id; strscpy(iface->p->name, iface->description, sizeof(iface->p->name)); iface->dev->bus = &mc.bus; - iface->dev->parent = &mc.dev; iface->dev->groups = interface_attr_groups; dev_set_drvdata(iface->dev, iface); if (device_register(iface->dev)) { - dev_err(&mc.dev, "registering iface->dev failed\n"); + dev_err(iface->dev, "registering iface->dev failed\n"); kfree(iface->p); put_device(iface->dev); ida_simple_remove(&mdev_id, id); @@ -1352,7 +1350,7 @@ int most_register_interface(struct most_interface *iface) mutex_init(&c->nq_mutex); list_add_tail(&c->list, &iface->p->channel_list); if (device_register(&c->dev)) { - dev_err(&mc.dev, "registering c->dev failed\n"); + dev_err(&c->dev, "registering c->dev failed\n"); goto err_free_most_channel; } } @@ -1452,11 +1450,6 @@ void most_resume_enqueue(struct most_interface *iface, int id) } EXPORT_SYMBOL_GPL(most_resume_enqueue); -static void release_most_sub(struct device *dev) -{ - dev_info(&mc.dev, "releasing most_subsystem\n"); -} - static int __init most_init(void) { int err; @@ -1472,25 +1465,17 @@ static int __init most_init(void) err = bus_register(&mc.bus); if (err) { - dev_err(&mc.dev, "Cannot register most bus\n"); + pr_err("Cannot register most bus\n"); return err; } err = driver_register(&mc.drv); if (err) { - dev_err(&mc.dev, "Cannot register core driver\n"); + pr_err("Cannot register core driver\n"); goto err_unregister_bus; } - mc.dev.init_name = "most_bus"; - mc.dev.release = release_most_sub; - if (device_register(&mc.dev)) { - err = -ENOMEM; - goto err_unregister_driver; - } configfs_init(); return 0; -err_unregister_driver: - driver_unregister(&mc.drv); err_unregister_bus: bus_unregister(&mc.bus); return err; @@ -1498,7 +1483,6 @@ err_unregister_bus: static void __exit most_exit(void) { - device_unregister(&mc.dev); driver_unregister(&mc.drv); bus_unregister(&mc.bus); ida_destroy(&mdev_id); diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index fb704be6f4f8..16593281fcda 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -856,6 +856,7 @@ static int dim2_probe(struct platform_device *pdev) dev->most_iface.driver_dev = &pdev->dev; dev->most_iface.dev = &dev->dev; dev->dev.init_name = "dim2_state"; + dev->dev.parent = &pdev->dev; ret = most_register_interface(&dev->most_iface); if (ret) { From d693e90d897854b09b9267350920cda964a66c11 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Thu, 23 Jan 2020 16:38:20 +0100 Subject: [PATCH 350/353] staging: most: core: remove container struct This patch declares and initializes the bus, bus driver and the component list without a container struct, as it introduces an unnecessary level of abstraction. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1579793906-5054-5-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 66 ++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 37ee00bb8d53..82525f5f4fd7 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -28,14 +28,7 @@ static struct ida mdev_id; static int dummy_num_buffers; - -static struct mostcore { - struct device_driver drv; - struct bus_type bus; - struct list_head comp_list; -} mc; - -#define to_driver(d) container_of(d, struct mostcore, drv) +static struct list_head comp_list; struct pipe { struct most_component *comp; @@ -457,7 +450,7 @@ static struct most_component *match_component(char *name) { struct most_component *comp; - list_for_each_entry(comp, &mc.comp_list, list) { + list_for_each_entry(comp, &comp_list, list) { if (!strcmp(comp->name, name)) return comp; } @@ -499,11 +492,24 @@ static int print_links(struct device *dev, void *data) return 0; } +static int most_match(struct device *dev, struct device_driver *drv) +{ + if (!strcmp(dev_name(dev), "most")) + return 0; + else + return 1; +} + +static struct bus_type mostbus = { + .name = "most", + .match = most_match, +}; + static ssize_t links_show(struct device_driver *drv, char *buf) { struct show_links_data d = { .buf = buf }; - bus_for_each_dev(&mc.bus, NULL, &d, print_links); + bus_for_each_dev(&mostbus, NULL, &d, print_links); return d.offs; } @@ -512,7 +518,7 @@ static ssize_t components_show(struct device_driver *drv, char *buf) struct most_component *comp; int offs = 0; - list_for_each_entry(comp, &mc.comp_list, list) { + list_for_each_entry(comp, &comp_list, list) { offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s\n", comp->name); } @@ -530,7 +536,7 @@ static struct most_channel *get_channel(char *mdev, char *mdev_ch) struct most_interface *iface; struct most_channel *c, *tmp; - dev = bus_find_device_by_name(&mc.bus, NULL, mdev); + dev = bus_find_device_by_name(&mostbus, NULL, mdev); if (!dev) return NULL; put_device(dev); @@ -722,13 +728,11 @@ static const struct attribute_group *mc_attr_groups[] = { NULL, }; -static int most_match(struct device *dev, struct device_driver *drv) -{ - if (!strcmp(dev_name(dev), "most")) - return 0; - else - return 1; -} +static struct device_driver mostbus_driver = { + .name = "most_core", + .bus = &mostbus, + .groups = mc_attr_groups, +}; static inline void trash_mbo(struct mbo *mbo) { @@ -1221,7 +1225,7 @@ int most_register_component(struct most_component *comp) pr_err("Bad component\n"); return -EINVAL; } - list_add_tail(&comp->list, &mc.comp_list); + list_add_tail(&comp->list, &comp_list); return 0; } EXPORT_SYMBOL_GPL(most_register_component); @@ -1255,7 +1259,7 @@ int most_deregister_component(struct most_component *comp) return -EINVAL; } - bus_for_each_dev(&mc.bus, NULL, comp, disconnect_channels); + bus_for_each_dev(&mostbus, NULL, comp, disconnect_channels); list_del(&comp->list); return 0; } @@ -1302,7 +1306,7 @@ int most_register_interface(struct most_interface *iface) INIT_LIST_HEAD(&iface->p->channel_list); iface->p->dev_id = id; strscpy(iface->p->name, iface->description, sizeof(iface->p->name)); - iface->dev->bus = &mc.bus; + iface->dev->bus = &mostbus; iface->dev->groups = interface_attr_groups; dev_set_drvdata(iface->dev, iface); if (device_register(iface->dev)) { @@ -1454,21 +1458,15 @@ static int __init most_init(void) { int err; - INIT_LIST_HEAD(&mc.comp_list); + INIT_LIST_HEAD(&comp_list); ida_init(&mdev_id); - mc.bus.name = "most", - mc.bus.match = most_match, - mc.drv.name = "most_core", - mc.drv.bus = &mc.bus, - mc.drv.groups = mc_attr_groups; - - err = bus_register(&mc.bus); + err = bus_register(&mostbus); if (err) { pr_err("Cannot register most bus\n"); return err; } - err = driver_register(&mc.drv); + err = driver_register(&mostbus_driver); if (err) { pr_err("Cannot register core driver\n"); goto err_unregister_bus; @@ -1477,14 +1475,14 @@ static int __init most_init(void) return 0; err_unregister_bus: - bus_unregister(&mc.bus); + bus_unregister(&mostbus); return err; } static void __exit most_exit(void) { - driver_unregister(&mc.drv); - bus_unregister(&mc.bus); + driver_unregister(&mostbus_driver); + bus_unregister(&mostbus); ida_destroy(&mdev_id); } From b7935e52dd98696a8c1379f5b67b0c344ee3bc35 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Thu, 23 Jan 2020 16:38:21 +0100 Subject: [PATCH 351/353] staging: most: core: fix logging messages This patch fixes the module's logging messages. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1579793906-5054-6-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 82525f5f4fd7..0c4ae6920d77 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -143,7 +143,7 @@ static void flush_channel_fifos(struct most_channel *c) spin_unlock_irqrestore(&c->fifo_lock, hf_flags); if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo)))) - dev_warn(&c->dev, "fifo | trash fifo not empty\n"); + dev_warn(&c->dev, "Channel or trash fifo not empty\n"); } /** @@ -629,7 +629,7 @@ int most_set_cfg_datatype(char *mdev, char *mdev_ch, char *buf) } if (i == ARRAY_SIZE(ch_data_type)) - dev_warn(&c->dev, "invalid attribute settings\n"); + dev_warn(&c->dev, "Invalid attribute settings\n"); return 0; } @@ -799,7 +799,7 @@ static int hdm_enqueue_thread(void *data) mutex_unlock(&c->nq_mutex); if (unlikely(ret)) { - dev_err(&c->dev, "hdm enqueue failed\n"); + dev_err(&c->dev, "Buffer enqueue failed\n"); nq_hdm_mbo(mbo); c->hdm_enqueue_task = NULL; return 0; @@ -926,7 +926,7 @@ flush_fifos: void most_submit_mbo(struct mbo *mbo) { if (WARN_ONCE(!mbo || !mbo->context, - "bad mbo or missing channel reference\n")) + "Bad buffer or missing channel reference\n")) return; nq_hdm_mbo(mbo); @@ -945,8 +945,6 @@ static void most_write_completion(struct mbo *mbo) struct most_channel *c; c = mbo->context; - if (mbo->status == MBO_E_INVAL) - dev_warn(&c->dev, "Tx MBO status: invalid\n"); if (unlikely(c->is_poisoned || (mbo->status == MBO_E_CLOSE))) trash_mbo(mbo); else @@ -1105,14 +1103,14 @@ int most_start_channel(struct most_interface *iface, int id, goto out; /* already started by another component */ if (!try_module_get(iface->mod)) { - dev_err(&c->dev, "failed to acquire HDM lock\n"); + dev_err(&c->dev, "Failed to acquire HDM lock\n"); mutex_unlock(&c->start_mutex); return -ENOLCK; } c->cfg.extra_len = 0; if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) { - dev_err(&c->dev, "channel configuration failed. Go check settings...\n"); + dev_err(&c->dev, "Channel configuration failed. Go check settings...\n"); ret = -EINVAL; goto err_put_module; } @@ -1186,7 +1184,7 @@ int most_stop_channel(struct most_interface *iface, int id, c->is_poisoned = true; if (c->iface->poison_channel(c->iface, c->channel_id)) { - dev_err(&c->dev, "Cannot stop channel %d of mdev %s\n", c->channel_id, + dev_err(&c->dev, "Failed to stop channel %d of interface %s\n", c->channel_id, c->iface->description); mutex_unlock(&c->start_mutex); return -EAGAIN; @@ -1196,7 +1194,7 @@ int most_stop_channel(struct most_interface *iface, int id, #ifdef CMPL_INTERRUPTIBLE if (wait_for_completion_interruptible(&c->cleanup)) { - dev_err(&c->dev, "Interrupted while clean up ch %d\n", c->channel_id); + dev_err(&c->dev, "Interrupted while cleaning up channel %d\n", c->channel_id); mutex_unlock(&c->start_mutex); return -EINTR; } @@ -1293,7 +1291,7 @@ int most_register_interface(struct most_interface *iface) id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL); if (id < 0) { - dev_err(iface->dev, "Failed to alloc mdev ID\n"); + dev_err(iface->dev, "Failed to allocate device ID\n"); return id; } @@ -1310,7 +1308,7 @@ int most_register_interface(struct most_interface *iface) iface->dev->groups = interface_attr_groups; dev_set_drvdata(iface->dev, iface); if (device_register(iface->dev)) { - dev_err(iface->dev, "registering iface->dev failed\n"); + dev_err(iface->dev, "Failed to register interface device\n"); kfree(iface->p); put_device(iface->dev); ida_simple_remove(&mdev_id, id); @@ -1354,7 +1352,7 @@ int most_register_interface(struct most_interface *iface) mutex_init(&c->nq_mutex); list_add_tail(&c->list, &iface->p->channel_list); if (device_register(&c->dev)) { - dev_err(&c->dev, "registering c->dev failed\n"); + dev_err(&c->dev, "Failed to register channel device\n"); goto err_free_most_channel; } } @@ -1463,12 +1461,12 @@ static int __init most_init(void) err = bus_register(&mostbus); if (err) { - pr_err("Cannot register most bus\n"); + pr_err("Failed to register most bus\n"); return err; } err = driver_register(&mostbus_driver); if (err) { - pr_err("Cannot register core driver\n"); + pr_err("Failed to register core driver\n"); goto err_unregister_bus; } configfs_init(); From f9e6b51a998da782cfc201dc9309d3a3d8579fef Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Thu, 23 Jan 2020 16:38:22 +0100 Subject: [PATCH 352/353] staging: next: configfs: fix release link The functions link_destroy and link_release are both deleting list items. link_release, however, does not check whether a certain link has already been deleted from the list by function link_destroy. By fixing this this patch prevents a kernel crash when removing the configuration directory of a link that already has been destroyed. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1579793906-5054-7-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/configfs.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/staging/most/configfs.c b/drivers/staging/most/configfs.c index 034ab96ef69e..9a961222f458 100644 --- a/drivers/staging/most/configfs.c +++ b/drivers/staging/most/configfs.c @@ -128,6 +128,8 @@ static ssize_t mdev_link_create_link_store(struct config_item *item, return ret; list_add_tail(&mdev_link->list, &mdev_link_list); mdev_link->create_link = tmp; + mdev_link->destroy_link = false; + return count; } @@ -143,13 +145,16 @@ static ssize_t mdev_link_destroy_link_store(struct config_item *item, return ret; if (!tmp) return count; - mdev_link->destroy_link = tmp; + ret = most_remove_link(mdev_link->device, mdev_link->channel, mdev_link->comp); if (ret) return ret; if (!list_empty(&mdev_link_list)) list_del(&mdev_link->list); + + mdev_link->destroy_link = tmp; + return count; } @@ -378,13 +383,20 @@ static void mdev_link_release(struct config_item *item) struct mdev_link *mdev_link = to_mdev_link(item); int ret; - if (!list_empty(&mdev_link_list)) { - ret = most_remove_link(mdev_link->device, mdev_link->channel, - mdev_link->comp); - if (ret && (ret != -ENODEV)) - pr_err("Removing link failed.\n"); - list_del(&mdev_link->list); + if (mdev_link->destroy_link) + goto free_item; + + ret = most_remove_link(mdev_link->device, mdev_link->channel, + mdev_link->comp); + if (ret) { + pr_err("Removing link failed.\n"); + goto free_item; } + + if (!list_empty(&mdev_link_list)) + list_del(&mdev_link->list); + +free_item: kfree(to_mdev_link(item)); } From fc157998b8257fb9cfe753e7f4af1411da995c9b Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Thu, 23 Jan 2020 16:38:23 +0100 Subject: [PATCH 353/353] staging: most: usb: check for NULL device Check if the dci structer has been allocated before trying to release it. Signed-off-by: Christian Gromm Link: https://lore.kernel.org/r/1579793906-5054-8-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/usb/usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c index dcc78cd870b8..0bda88c4bc89 100644 --- a/drivers/staging/most/usb/usb.c +++ b/drivers/staging/most/usb/usb.c @@ -1218,7 +1218,8 @@ static void hdm_disconnect(struct usb_interface *interface) del_timer_sync(&mdev->link_stat_timer); cancel_work_sync(&mdev->poll_work_obj); - device_unregister(&mdev->dci->dev); + if (mdev->dci) + device_unregister(&mdev->dci->dev); most_deregister_interface(&mdev->iface); kfree(mdev->busy_urbs);