We need the staging fixes in here as well.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
values are 'base' and 'lid'.
What: /sys/bus/iio/devices/iio:deviceX/id
-Date: Septembre 2017
+Date: September 2017
KernelVersion: 4.14
Contact: linux-iio@vger.kernel.org
Description:
- This attribute is exposed by the CrOS EC legacy accelerometer
- driver and represents the sensor ID as exposed by the EC. This
- ID is used by the Android sensor service hardware abstraction
- layer (sensor HAL) through the Android container on ChromeOS.
+ This attribute is exposed by the CrOS EC sensors driver and
+ represents the sensor ID as exposed by the EC. This ID is used
+ by the Android sensor service hardware abstraction layer (sensor
+ HAL) through the Android container on ChromeOS.
--- /dev/null
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/accelerometers/adi,adxl345.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices ADXL345/ADXL375 3-Axis Digital Accelerometers
+
+maintainers:
+ - Michael Hennerich <michael.hennerich@analog.com>
+
+description: |
+ Analog Devices ADXL345/ADXL375 3-Axis Digital Accelerometers that supports
+ both I2C & SPI interfaces.
+ http://www.analog.com/en/products/mems/accelerometers/adxl345.html
+ http://www.analog.com/en/products/sensors-mems/accelerometers/adxl375.html
+
+properties:
+ compatible:
+ enum:
+ - adi,adxl345
+ - adi,adxl375
+
+ reg:
+ maxItems: 1
+
+ spi-cpha: true
+
+ spi-cpol: true
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Example for a I2C device node */
+ accelerometer@2a {
+ compatible = "adi,adxl345";
+ reg = <0x53>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ spi0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Example for a SPI device node */
+ accelerometer@0 {
+ compatible = "adi,adxl345";
+ reg = <0>;
+ spi-max-frequency = <5000000>;
+ spi-cpol;
+ spi-cpha;
+ interrupt-parent = <&gpio0>;
+ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+++ /dev/null
-Analog Devices ADXL345/ADXL375 3-Axis Digital Accelerometers
-
-http://www.analog.com/en/products/mems/accelerometers/adxl345.html
-http://www.analog.com/en/products/sensors-mems/accelerometers/adxl375.html
-
-Required properties:
- - compatible : should be one of
- "adi,adxl345"
- "adi,adxl375"
- - reg : the I2C address or SPI chip select number of the sensor
-
-Required properties for SPI bus usage:
- - spi-max-frequency : set maximum clock frequency, must be 5000000
- - spi-cpol and spi-cpha : must be defined for adxl345 to enable SPI mode 3
-
-Optional properties:
- - interrupts: interrupt mapping for IRQ as documented in
- Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
-
-Example for a I2C device node:
-
- accelerometer@2a {
- compatible = "adi,adxl345";
- reg = <0x53>;
- interrupt-parent = <&gpio1>;
- interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
- };
-
-Example for a SPI device node:
-
- accelerometer@0 {
- compatible = "adi,adxl345";
- reg = <0>;
- spi-max-frequency = <5000000>;
- spi-cpol;
- spi-cpha;
- interrupt-parent = <&gpio1>;
- interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
- };
- compatible: Should be one of:
- "mediatek,mt2701-auxadc": For MT2701 family of SoCs
- "mediatek,mt2712-auxadc": For MT2712 family of SoCs
+ - "mediatek,mt6765-auxadc": For MT6765 family of SoCs
- "mediatek,mt7622-auxadc": For MT7622 family of SoCs
- "mediatek,mt8173-auxadc": For MT8173 family of SoCs
+ - "mediatek,mt8183-auxadc", "mediatek,mt8173-auxadc": For MT8183 family of SoCs
- reg: Address range of the AUXADC unit.
- clocks: Should contain a clock specifier for each entry in clock-names
- clock-names: Should contain "main".
+++ /dev/null
-* ISL 29018/29023/29035 I2C ALS, Proximity, and Infrared sensor
-
-Required properties:
-
- - compatible: Should be one of
- "isil,isl29018"
- "isil,isl29023"
- "isil,isl29035"
- - reg: the I2C address of the device
-
-Optional properties:
-
- - interrupts: the sole interrupt generated by the device
-
- Refer to interrupt-controller/interrupts.txt for generic interrupt client
- node bindings.
-
- - vcc-supply: phandle to the regulator that provides power to the sensor.
-
-Example:
-
-isl29018@44 {
- compatible = "isil,isl29018";
- reg = <0x44>;
- interrupt-parent = <&gpio>;
- interrupts = <TEGRA_GPIO(Z, 2) IRQ_TYPE_LEVEL_HIGH>;
-};
--- /dev/null
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/light/isl29018.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: |
+ Intersil 29018/29023/29035 Ambient Light, Infrared Light, and Proximity Sensor
+
+maintainers:
+ - Brian Masney <masneyb@onstation.org>
+
+description: |
+ Ambient and infrared light sensing with proximity detection over an i2c
+ interface.
+
+ https://www.renesas.com/us/en/www/doc/datasheet/isl29018.pdf
+ https://www.renesas.com/us/en/www/doc/datasheet/isl29023.pdf
+ https://www.renesas.com/us/en/www/doc/datasheet/isl29035.pdf
+
+properties:
+ compatible:
+ enum:
+ - isil,isl29018
+ - isil,isl29023
+ - isil,isl29035
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ vcc-supply:
+ description: Regulator that provides power to the sensor
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sensor@44 {
+ compatible = "isil,isl29018";
+ reg = <0x44>;
+ interrupts-extended = <&msmgpio 61 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+...
+++ /dev/null
-* TAOS TSL 2580/2581/2583 ALS sensor
-
-Required properties:
-
- - compatible: Should be one of
- "amstaos,tsl2580"
- "amstaos,tsl2581"
- "amstaos,tsl2583"
- - reg: the I2C address of the device
-
-Optional properties:
-
- - interrupts: the sole interrupt generated by the device
-
- Refer to interrupt-controller/interrupts.txt for generic interrupt client
- node bindings.
-
- - vcc-supply: phandle to the regulator that provides power to the sensor.
-
-Example:
-
-tsl2581@29 {
- compatible = "amstaos,tsl2581";
- reg = <0x29>;
-};
--- /dev/null
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/light/tsl2583.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: AMS/TAOS Ambient Light Sensor (ALS)
+
+maintainers:
+ - Brian Masney <masneyb@onstation.org>
+
+description: |
+ Ambient light sensing with an i2c interface.
+
+properties:
+ compatible:
+ enum:
+ - amstaos,tsl2580
+ - amstaos,tsl2581
+ - amstaos,tsl2583
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ vcc-supply:
+ description: Regulator that provides power to the sensor
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ light-sensor@29 {
+ compatible = "amstaos,tsl2581";
+ reg = <0x29>;
+ };
+ };
+...
+++ /dev/null
-* AMS/TAOS ALS and proximity sensor
-
-Required properties:
-
- - compatible: Should be one of
- "amstaos,tsl2571"
- "amstaos,tsl2671"
- "amstaos,tmd2671"
- "amstaos,tsl2771"
- "amstaos,tmd2771"
- "amstaos,tsl2572"
- "amstaos,tsl2672"
- "amstaos,tmd2672"
- "amstaos,tsl2772"
- "amstaos,tmd2772"
- "avago,apds9930"
- - reg: the I2C address of the device
-
-Optional properties:
-
- - amstaos,proximity-diodes - proximity diodes to enable. <0>, <1>, or <0 1>
- are the only valid values.
- - led-max-microamp - current for the proximity LED. Must be 100000, 50000,
- 25000, or 13000.
- - vdd-supply: phandle to the regulator that provides power to the sensor.
- - vddio-supply: phandle to the regulator that provides power to the bus.
- - interrupts: the sole interrupt generated by the device
-
- Refer to interrupt-controller/interrupts.txt for generic interrupt client
- node bindings.
-
-Example:
-
-tsl2772@39 {
- compatible = "amstaos,tsl2772";
- reg = <0x39>;
- interrupts-extended = <&msmgpio 61 IRQ_TYPE_EDGE_FALLING>;
- vdd-supply = <&pm8941_l17>;
- vddio-supply = <&pm8941_lvs1>;
- amstaos,proximity-diodes = <0>;
- led-max-microamp = <100000>;
-};
--- /dev/null
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/light/tsl2772.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: AMS/TAOS Ambient Light Sensor (ALS) and Proximity Detector
+
+maintainers:
+ - Brian Masney <masneyb@onstation.org>
+
+description: |
+ Ambient light sensing and proximity detection with an i2c interface.
+ https://ams.com/documents/20143/36005/TSL2772_DS000181_2-00.pdf
+
+properties:
+ compatible:
+ enum:
+ - amstaos,tsl2571
+ - amstaos,tsl2671
+ - amstaos,tmd2671
+ - amstaos,tsl2771
+ - amstaos,tmd2771
+ - amstaos,tsl2572
+ - amstaos,tsl2672
+ - amstaos,tmd2672
+ - amstaos,tsl2772
+ - amstaos,tmd2772
+ - avago,apds9930
+
+ reg:
+ maxItems: 1
+
+ amstaos,proximity-diodes:
+ description: Proximity diodes to enable
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32-array
+ - minItems: 1
+ maxItems: 2
+ items:
+ minimum: 0
+ maximum: 1
+
+ interrupts:
+ maxItems: 1
+
+ led-max-microamp:
+ description: Current for the proximity LED
+ enum:
+ - 13000
+ - 25000
+ - 50000
+ - 100000
+
+ vdd-supply:
+ description: Regulator that provides power to the sensor
+
+ vddio-supply:
+ description: Regulator that provides power to the bus
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sensor@39 {
+ compatible = "amstaos,tsl2772";
+ reg = <0x39>;
+ interrupts-extended = <&msmgpio 61 IRQ_TYPE_EDGE_FALLING>;
+ vdd-supply = <&pm8941_l17>;
+ vddio-supply = <&pm8941_lvs1>;
+ amstaos,proximity-diodes = <0>;
+ led-max-microamp = <100000>;
+ };
+ };
+...
W: http://ez.analog.com/community/linux-device-drivers
S: Supported
F: drivers/input/misc/adxl34x.c
+F: Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
M: Stefan Popa <stefan.popa@analog.com>
S: Maintained
F: drivers/staging/erofs/
+STAGING - FIELDBUS SUBSYSTEM
+M: Sven Van Asbroeck <TheSven73@gmail.com>
+S: Maintained
+F: drivers/staging/fieldbus/*
+F: drivers/staging/fieldbus/Documentation/
+
+STAGING - HMS ANYBUS-S BUS
+M: Sven Van Asbroeck <TheSven73@gmail.com>
+S: Maintained
+F: drivers/staging/fieldbus/anybuss/
+
STAGING - INDUSTRIAL IO
M: Jonathan Cameron <jic23@kernel.org>
L: linux-iio@vger.kernel.org
#include <linux/module.h>
#include <linux/regmap.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include "adxl372.h"
};
MODULE_DEVICE_TABLE(spi, adxl372_spi_id);
+static const struct of_device_id adxl372_of_match[] = {
+ { .compatible = "adi,adxl372" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, adxl372_of_match);
+
static struct spi_driver adxl372_spi_driver = {
.driver = {
.name = "adxl372_spi",
+ .of_match_table = adxl372_of_match,
},
.probe = adxl372_spi_probe,
.id_table = adxl372_spi_id,
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/device.h>
#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/module.h>
#include <linux/slab.h>
};
MODULE_DEVICE_TABLE(spi, kxsd9_spi_id);
+static const struct of_device_id kxsd9_of_match[] = {
+ { .compatible = "kionix,kxsd9" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, kxsd9_of_match);
+
static struct spi_driver kxsd9_spi_driver = {
.driver = {
.name = "kxsd9",
.pm = &kxsd9_dev_pm_ops,
+ .of_match_table = kxsd9_of_match,
},
.probe = kxsd9_spi_probe,
.remove = kxsd9_spi_remove,
static ssize_t at91_adc_get_fifo_state(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev =
- platform_get_drvdata(to_platform_device(dev));
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct at91_adc_state *st = iio_priv(indio_dev);
return scnprintf(buf, PAGE_SIZE, "%d\n", !!st->dma_st.dma_chan);
static ssize_t at91_adc_get_watermark(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct iio_dev *indio_dev =
- platform_get_drvdata(to_platform_device(dev));
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct at91_adc_state *st = iio_priv(indio_dev);
return scnprintf(buf, PAGE_SIZE, "%d\n", st->dma_st.watermark);
static __maybe_unused int at91_adc_suspend(struct device *dev)
{
- struct iio_dev *indio_dev =
- platform_get_drvdata(to_platform_device(dev));
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct at91_adc_state *st = iio_priv(indio_dev);
/*
static __maybe_unused int at91_adc_resume(struct device *dev)
{
- struct iio_dev *indio_dev =
- platform_get_drvdata(to_platform_device(dev));
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct at91_adc_state *st = iio_priv(indio_dev);
int ret;
#ifdef CONFIG_PM_SLEEP
static int at91_adc_suspend(struct device *dev)
{
- struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev));
+ struct iio_dev *idev = dev_get_drvdata(dev);
struct at91_adc_state *st = iio_priv(idev);
pinctrl_pm_select_sleep_state(dev);
static int at91_adc_resume(struct device *dev)
{
- struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev));
+ struct iio_dev *idev = dev_get_drvdata(dev);
struct at91_adc_state *st = iio_priv(idev);
clk_prepare_enable(st->clk);
#define MT6577_AUXADC_POWER_READY_MS 1
#define MT6577_AUXADC_SAMPLE_READY_US 25
+struct mtk_auxadc_compatible {
+ bool sample_data_cali;
+ bool check_global_idle;
+};
+
struct mt6577_auxadc_device {
void __iomem *reg_base;
struct clk *adc_clk;
struct mutex lock;
+ const struct mtk_auxadc_compatible *dev_comp;
+};
+
+static const struct mtk_auxadc_compatible mt8173_compat = {
+ .sample_data_cali = false,
+ .check_global_idle = true,
+};
+
+static const struct mtk_auxadc_compatible mt6765_compat = {
+ .sample_data_cali = true,
+ .check_global_idle = false,
};
#define MT6577_AUXADC_CHANNEL(idx) { \
MT6577_AUXADC_CHANNEL(15),
};
+static int mt_auxadc_get_cali_data(int rawdata, bool enable_cali)
+{
+ return rawdata;
+}
+
static inline void mt6577_auxadc_mod_reg(void __iomem *reg,
u32 or_mask, u32 and_mask)
{
/* we must delay here for hardware sample channel data */
udelay(MT6577_AUXADC_SAMPLE_READY_US);
- /* check MTK_AUXADC_CON2 if auxadc is idle */
- ret = readl_poll_timeout(adc_dev->reg_base + MT6577_AUXADC_CON2, val,
- ((val & MT6577_AUXADC_STA) == 0),
- MT6577_AUXADC_SLEEP_US,
- MT6577_AUXADC_TIMEOUT_US);
- if (ret < 0) {
- dev_err(indio_dev->dev.parent,
- "wait for auxadc idle time out\n");
- goto err_timeout;
+ if (adc_dev->dev_comp->check_global_idle) {
+ /* check MTK_AUXADC_CON2 if auxadc is idle */
+ ret = readl_poll_timeout(adc_dev->reg_base + MT6577_AUXADC_CON2,
+ val, ((val & MT6577_AUXADC_STA) == 0),
+ MT6577_AUXADC_SLEEP_US,
+ MT6577_AUXADC_TIMEOUT_US);
+ if (ret < 0) {
+ dev_err(indio_dev->dev.parent,
+ "wait for auxadc idle time out\n");
+ goto err_timeout;
+ }
}
/* read channel and make sure ready bit == 1 */
int *val2,
long info)
{
+ struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
+
switch (info) {
case IIO_CHAN_INFO_PROCESSED:
*val = mt6577_auxadc_read(indio_dev, chan);
chan->channel);
return *val;
}
+ if (adc_dev->dev_comp->sample_data_cali)
+ *val = mt_auxadc_get_cali_data(*val, true);
return IIO_VAL_INT;
default:
mt6577_auxadc_resume);
static const struct of_device_id mt6577_auxadc_of_match[] = {
- { .compatible = "mediatek,mt2701-auxadc", },
- { .compatible = "mediatek,mt2712-auxadc", },
- { .compatible = "mediatek,mt7622-auxadc", },
- { .compatible = "mediatek,mt8173-auxadc", },
+ { .compatible = "mediatek,mt2701-auxadc", .data = &mt8173_compat},
+ { .compatible = "mediatek,mt2712-auxadc", .data = &mt8173_compat},
+ { .compatible = "mediatek,mt7622-auxadc", .data = &mt8173_compat},
+ { .compatible = "mediatek,mt8173-auxadc", .data = &mt8173_compat},
+ { .compatible = "mediatek,mt6765-auxadc", .data = &mt6765_compat},
{ }
};
MODULE_DEVICE_TABLE(of, mt6577_auxadc_of_match);
int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
- if (!indio_dev) {
- dev_err(dev, "Failed to allocate IIO device.\n");
+ if (!indio_dev)
return -ENOMEM;
- }
priv = iio_priv(indio_dev);
priv->dev = dev;
* So IRQ associated to filter instance 0 is dedicated to the Filter 0.
*/
irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ if (irq != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get IRQ: %d\n", irq);
+ return irq;
+ }
+
ret = devm_request_irq(dev, irq, stm32_dfsdm_irq,
0, pdev->name, adc);
if (ret < 0) {
}
priv->dfsdm.phys_base = res->start;
priv->dfsdm.base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->dfsdm.base))
+ return PTR_ERR(priv->dfsdm.base);
/*
* "dfsdm" clock is mandatory for DFSDM peripheral clocking.
*/
priv->clk = devm_clk_get(&pdev->dev, "dfsdm");
if (IS_ERR(priv->clk)) {
- dev_err(&pdev->dev, "No stm32_dfsdm_clk clock found\n");
- return -EINVAL;
+ ret = PTR_ERR(priv->clk);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to get clock (%d)\n", ret);
+ return ret;
}
priv->aclk = devm_clk_get(&pdev->dev, "audio");
mutex_lock(&info->lock);
+ reinit_completion(&info->completion);
+
info->channel = (u8)chan->channel;
if (info->channel > STMPE_ADC_LAST_NR) {
return -EINVAL;
}
- stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_EN,
- STMPE_ADC_CH(info->channel));
-
stmpe_reg_write(info->stmpe, STMPE_REG_ADC_CAPT,
STMPE_ADC_CH(info->channel));
- *val = info->value;
-
- ret = wait_for_completion_interruptible_timeout
- (&info->completion, STMPE_ADC_TIMEOUT);
+ ret = wait_for_completion_timeout(&info->completion, STMPE_ADC_TIMEOUT);
if (ret <= 0) {
+ stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA,
+ STMPE_ADC_CH(info->channel));
mutex_unlock(&info->lock);
- if (ret == 0)
- return -ETIMEDOUT;
- else
- return ret;
+ return -ETIMEDOUT;
}
*val = info->value;
mutex_lock(&info->lock);
+ reinit_completion(&info->completion);
+
info->channel = (u8)chan->channel;
if (info->channel != STMPE_TEMP_CHANNEL) {
stmpe_reg_write(info->stmpe, STMPE_REG_TEMP_CTRL,
STMPE_START_ONE_TEMP_CONV);
- ret = wait_for_completion_interruptible_timeout
- (&info->completion, STMPE_ADC_TIMEOUT);
+ ret = wait_for_completion_timeout(&info->completion, STMPE_ADC_TIMEOUT);
if (ret <= 0) {
mutex_unlock(&info->lock);
- if (ret == 0)
- return -ETIMEDOUT;
- else
- return ret;
+ return -ETIMEDOUT;
}
/*
if (ret)
return ret;
+ stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_EN,
+ ~(norequest_mask & 0xFF));
+
+ stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA,
+ ~(norequest_mask & 0xFF));
+
return devm_iio_device_register(&pdev->dev, indio_dev);
}
.pm = &stmpe_adc_pm_ops,
},
};
-
module_platform_driver(stmpe_adc_driver);
+static const struct of_device_id stmpe_adc_ids[] = {
+ { .compatible = "st,stmpe-adc", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, stmpe_adc_ids);
+
MODULE_AUTHOR("Stefan Agner <stefan.agner@toradex.com>");
MODULE_DESCRIPTION("STMPEXXX ADC driver");
MODULE_LICENSE("GPL v2");
+// SPDX-License-Identifier: GPL-2.0
/* ADC driver for sunxi platforms' (A10, A13 and A31) GPADC
*
* Copyright (c) 2016 Quentin Schulz <quentin.schulz@free-electrons.com>
*
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- *
* The Allwinner SoCs all have an ADC that can also act as a touchscreen
* controller and a thermal sensor.
* The thermal sensor works only when the ADC acts as a touchscreen controller
return ret ? ret : len;
}
+static ssize_t cros_ec_sensors_id(struct iio_dev *indio_dev,
+ uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+ struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", st->param.info.sensor_num);
+}
+
static ssize_t cros_ec_sensors_loc(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan,
char *buf)
.write = cros_ec_sensors_calibrate
},
{
+ .name = "id",
+ .shared = IIO_SHARED_BY_ALL,
+ .read = cros_ec_sensors_id
+ },
+ {
.name = "location",
.shared = IIO_SHARED_BY_ALL,
.read = cros_ec_sensors_loc
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/property.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/gpio/consumer.h>
{
struct ad5758_state *st = iio_priv(indio_dev);
bool pwr_down;
- unsigned int dc_dc_mode, dac_config_mode, val;
+ unsigned int dac_config_mode, val;
unsigned long int dac_config_msk;
int ret;
return ret;
mutex_lock(&st->lock);
- if (pwr_down) {
- dc_dc_mode = AD5758_DCDC_MODE_POWER_OFF;
+ if (pwr_down)
val = 0;
- } else {
- dc_dc_mode = st->dc_dc_mode;
+ else
val = 1;
- }
dac_config_mode = AD5758_DAC_CONFIG_OUT_EN_MODE(val) |
AD5758_DAC_CONFIG_INT_EN_MODE(val);
};
MODULE_DEVICE_TABLE(spi, ad5758_id);
+static const struct of_device_id ad5758_of_match[] = {
+ { .compatible = "adi,ad5758" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ad5758_of_match);
+
static struct spi_driver ad5758_driver = {
.driver = {
.name = KBUILD_MODNAME,
+ .of_match_table = ad5758_of_match,
},
.probe = ad5758_probe,
.id_table = ad5758_id,
indio_dev->dev.of_node = client->dev.of_node;
indio_dev->dev.parent = &client->dev;
- if (!client->dev.of_node) {
- dev_err(&client->dev,
- "Not found DT.\n");
- return -ENODEV;
- }
-
data->vcc_reg = devm_regulator_get(&client->dev, "vcc");
if (IS_ERR(data->vcc_reg)) {
dev_err(&client->dev,
if (ret < 0)
return ret;
- st->vco_freq = (pdata->vcxo_freq * (pdata->pll2_freq_doubler_en ? 2 : 1)
- / pdata->pll2_r2_div) * AD9523_PLL2_FB_NDIV(pdata->
- pll2_ndiv_a_cnt, pdata->pll2_ndiv_b_cnt);
+ st->vco_freq = div_u64((unsigned long long)pdata->vcxo_freq *
+ (pdata->pll2_freq_doubler_en ? 2 : 1) *
+ AD9523_PLL2_FB_NDIV(pdata->pll2_ndiv_a_cnt,
+ pdata->pll2_ndiv_b_cnt),
+ pdata->pll2_r2_div);
ret = ad9523_write(indio_dev, AD9523_PLL2_VCO_CTRL,
AD9523_PLL2_VCO_CALIBRATE);
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
};
MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id);
+static const struct of_device_id maxim_thermocouple_of_match[] = {
+ { .compatible = "maxim,max6675" },
+ { .compatible = "maxim,max31855" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, maxim_thermocouple_of_match);
+
static struct spi_driver maxim_thermocouple_driver = {
.driver = {
.name = MAXIM_THERMOCOUPLE_DRV_NAME,
+ .of_match_table = maxim_thermocouple_of_match,
},
.probe = maxim_thermocouple_probe,
.remove = maxim_thermocouple_remove,
EROFS_VERSION = "1.0pre1"
-ccflags-y += -Wall -DEROFS_VERSION=\"$(EROFS_VERSION)\"
+ccflags-y += -DEROFS_VERSION=\"$(EROFS_VERSION)\"
obj-$(CONFIG_EROFS_FS) += erofs.o
# staging requirement: to be self-contained in its own directory
struct erofs_vnode *vi = EROFS_V(inode);
struct erofs_inode_v1 *v1 = data;
const unsigned int advise = le16_to_cpu(v1->i_advise);
+ erofs_blk_t nblks = 0;
vi->data_mapping_mode = __inode_data_mapping(advise);
le32_to_cpu(v2->i_ctime_nsec);
inode->i_size = le64_to_cpu(v2->i_size);
+
+ /* total blocks for compressed files */
+ if (vi->data_mapping_mode == EROFS_INODE_LAYOUT_COMPRESSION)
+ nblks = le32_to_cpu(v2->i_u.compressed_blocks);
} else if (__inode_version(advise) == EROFS_INODE_LAYOUT_V1) {
struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb);
sbi->build_time_nsec;
inode->i_size = le32_to_cpu(v1->i_size);
+ if (vi->data_mapping_mode == EROFS_INODE_LAYOUT_COMPRESSION)
+ nblks = le32_to_cpu(v1->i_u.compressed_blocks);
} else {
errln("unsupported on-disk inode version %u of nid %llu",
__inode_version(advise), vi->nid);
return -EIO;
}
- /* measure inode.i_blocks as the generic filesystem */
- inode->i_blocks = ((inode->i_size - 1) >> 9) + 1;
+ if (!nblks)
+ /* measure inode.i_blocks as generic filesystems */
+ inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9;
+ else
+ inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK;
return 0;
}
return inode;
}
+int erofs_getattr(const struct path *path, struct kstat *stat,
+ u32 request_mask, unsigned int query_flags)
+{
+ struct inode *const inode = d_inode(path->dentry);
+ struct erofs_vnode *const vi = EROFS_V(inode);
+
+ if (vi->data_mapping_mode == EROFS_INODE_LAYOUT_COMPRESSION)
+ stat->attributes |= STATX_ATTR_COMPRESSED;
+
+ stat->attributes |= STATX_ATTR_IMMUTABLE;
+ stat->attributes_mask |= (STATX_ATTR_COMPRESSED |
+ STATX_ATTR_IMMUTABLE);
+
+ generic_fillattr(inode, stat);
+ return 0;
+}
+
const struct inode_operations erofs_generic_iops = {
+ .getattr = erofs_getattr,
#ifdef CONFIG_EROFS_FS_XATTR
.listxattr = erofs_listxattr,
#endif
const struct inode_operations erofs_symlink_iops = {
.get_link = page_get_link,
+ .getattr = erofs_getattr,
#ifdef CONFIG_EROFS_FS_XATTR
.listxattr = erofs_listxattr,
#endif
const struct inode_operations erofs_fast_symlink_iops = {
.get_link = simple_get_link,
+ .getattr = erofs_getattr,
#ifdef CONFIG_EROFS_FS_XATTR
.listxattr = erofs_listxattr,
#endif
}
struct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid, bool dir);
+int erofs_getattr(const struct path *path, struct kstat *stat,
+ u32 request_mask, unsigned int query_flags);
/* namei.c */
extern const struct inode_operations erofs_dir_iops;
const struct inode_operations erofs_dir_iops = {
.lookup = erofs_lookup,
+ .getattr = erofs_getattr,
#ifdef CONFIG_EROFS_FS_XATTR
.listxattr = erofs_listxattr,
#endif
if (tags == Z_EROFS_PAGE_TYPE_EXCLUSIVE)
return tagptr_unfold_ptr(t);
}
-
- if (unlikely(nr >= ctor->nr))
- BUG();
-
+ DBG_BUGON(nr >= ctor->nr);
return NULL;
}
* at a time for now.
*/
-static int read_reg_bus(void *context, unsigned int reg,
- unsigned int *val)
-{
- void __iomem *base = context;
-
- *val = readb(base + reg);
- return 0;
-}
-
-static int write_reg_bus(void *context, unsigned int reg,
- unsigned int val)
-{
- void __iomem *base = context;
-
- writeb(val, base + reg);
- return 0;
-}
+static const struct regmap_config arcx_regmap_cfg = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .max_register = 0x7ff,
+ .use_single_read = true,
+ .use_single_write = true,
+ /*
+ * single-byte parallel bus accesses are atomic, so don't
+ * require any synchronization.
+ */
+ .disable_locking = true,
+};
static struct regmap *create_parallel_regmap(struct platform_device *pdev,
int idx)
{
- struct regmap_config regmap_cfg = {
- .reg_bits = 11,
- .val_bits = 8,
- /*
- * single-byte parallel bus accesses are atomic, so don't
- * require any synchronization.
- */
- .disable_locking = true,
- .reg_read = read_reg_bus,
- .reg_write = write_reg_bus,
- };
struct resource *res;
void __iomem *base;
struct device *dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1);
- if (resource_size(res) < (1 << regmap_cfg.reg_bits))
- return ERR_PTR(-EINVAL);
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return ERR_CAST(base);
- return devm_regmap_init(dev, NULL, base, ®map_cfg);
+ return devm_regmap_init_mmio(dev, base, &arcx_regmap_cfg);
}
static struct anybuss_host *
return fbdev->write_area(fbdev, buf, size, offset);
}
-static unsigned int fieldbus_poll(struct file *filp, poll_table *wait)
+static __poll_t fieldbus_poll(struct file *filp, poll_table *wait)
{
struct fb_open_file *of = filp->private_data;
struct fieldbus_dev *fbdev = of->fbdev;
- unsigned int mask = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
+ __poll_t mask = EPOLLIN | EPOLLRDNORM | EPOLLOUT | EPOLLWRNORM;
poll_wait(filp, &fbdev->dc_wq, wait);
/* data changed ? */
if (fbdev->dc_event != of->dc_event)
- mask |= POLLPRI | POLLERR;
+ mask |= EPOLLPRI | EPOLLERR;
return mask;
}
config FSL_DPAA2
bool "Freescale DPAA2 devices"
depends on FSL_MC_BUS
- ---help---
+ help
Build drivers for Freescale DataPath Acceleration
Architecture (DPAA2) family of SoCs.
tristate "Freescale DPAA2 Ethernet Switch"
depends on FSL_DPAA2
depends on NET_SWITCHDEV
- ---help---
- Driver for Freescale DPAA2 Ethernet Switch. Select
- BRIDGE to have support for bridge tools.
+ help
+ Driver for Freescale DPAA2 Ethernet Switch. Select
+ BRIDGE to have support for bridge tools.
if ((vma->vm_flags & VM_WRITE) &&
!gasket_owned_by_current_tgid(&gasket_dev->dev_info)) {
dev_dbg(gasket_dev->dev,
- "Attempting to mmap a region for write without owning "
- "device.\n");
+ "Attempting to mmap a region for write without owning device.\n");
return false;
}
}
if (bar_index > 0 && is_coherent_region) {
dev_err(gasket_dev->dev,
- "double matching bar and coherent buffers for address "
- "0x%lx\n",
+ "double matching bar and coherent buffers for address 0x%lx\n",
raw_offset);
trace_gasket_mmap_exit(bar_index);
return -EINVAL;
*/
trace_gasket_ioctl_integer_data(arg);
dev_dbg(gasket_dev->dev,
- "Unknown ioctl cmd=0x%x not caught by "
- "gasket_is_supported_ioctl\n",
+ "Unknown ioctl cmd=0x%x not caught by gasket_is_supported_ioctl\n",
cmd);
retval = -EINVAL;
break;
* hardware register that contains the page table size.
*/
if (total_entries == ULONG_MAX) {
- dev_dbg(device, "Error reading page table size. "
- "Initializing page table with size 0\n");
+ dev_dbg(device,
+ "Error reading page table size. Initializing page table with size 0\n");
total_entries = 0;
}
if (ret <= 0) {
dev_err(pg_tbl->device,
- "get user pages failed for addr=0x%lx, "
- "offset=0x%lx [ret=%d]\n",
+ "get user pages failed for addr=0x%lx, offset=0x%lx [ret=%d]\n",
page_addr, offset, ret);
return ret ? ret : -ENOMEM;
}
if (page_lvl0_idx >= pg_tbl->num_extended_entries) {
dev_err(pg_tbl->device,
- "starting level 0 slot at %lu is too large, max is < "
- "%u\n", page_lvl0_idx, pg_tbl->num_extended_entries);
+ "starting level 0 slot at %lu is too large, max is < %u\n",
+ page_lvl0_idx, pg_tbl->num_extended_entries);
return true;
}
if (ret) {
dev_addr_end = dev_addr + (num_pages / PAGE_SIZE) - 1;
dev_err(pg_tbl->device,
- "page table slots (%lu,%lu) (@ 0x%lx) to (%lu,%lu) are "
- "not available\n",
+ "page table slots (%lu,%lu) (@ 0x%lx) to (%lu,%lu) are not available\n",
gasket_extended_lvl0_page_idx(pg_tbl, dev_addr),
dev_addr,
gasket_extended_lvl1_page_idx(pg_tbl, dev_addr),
Say yes here to build support for Analog Devices AD7816/7/8
temperature sensors and ADC.
+ To compile this driver as a module, choose M here: the
+ module will be called ad7816.
+
config AD7192
tristate "Analog Devices AD7190 AD7192 AD7193 AD7195 ADC driver"
depends on SPI
chip->dac_bits = 8;
chip->ldac_pin = devm_gpiod_get_optional(dev, "adi,ldac",
- GPIOD_OUT_LOW);
+ GPIOD_OUT_LOW);
if (IS_ERR(chip->ldac_pin)) {
ret = PTR_ERR(chip->ldac_pin);
dev_err(dev, "Failed to request ldac GPIO: %d\n", ret);
If unsure, say N.
config KPC2000_SPI
- tristate "Kaktronics KPC SPI device"
+ tristate "Daktronics KPC SPI device"
depends on KPC2000 && SPI
help
Say Y here if you wish to support the Daktronics KPC PCI
If unsure, say N.
config KPC2000_I2C
- tristate "Kaktronics KPC I2C device"
+ tristate "Daktronics KPC I2C device"
depends on KPC2000 && I2C
help
Say Y here if you wish to support the Daktronics KPC PCI
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_KPC2000) += kpc2000/
-obj-$(CONFIG_KPC2000_I2C) += kpc_i2c/
-obj-$(CONFIG_KPC2000_SPI) += kpc_spi/
+obj-$(CONFIG_KPC2000_I2C) += kpc2000_i2c.o
+obj-$(CONFIG_KPC2000_SPI) += kpc2000_spi.o
obj-$(CONFIG_KPC2000_DMA) += kpc_dma/
- the kpc_spi driver doesn't seem to let multiple transactions (to different instances of the core) happen in parallel...
- The kpc_i2c driver is a hot mess, it should probably be cleaned up a ton. It functions against current hardware though.
-- pcard->card_num in kp2000_pcie_probe() is a global variable and needs atomic / locking / something better.
-- probe_core_uio() probably needs error handling
-- the loop in kp2000_probe_cores() that uses probe_core_uio() also probably needs error handling
- would be nice if the AIO fileops in kpc_dma could be made to work
- probably want to add a CONFIG_ option to control compilation of the AIO functions
- if the AIO fileops in kpc_dma start working, next would be making iov_count > 1 work too
# SPDX-License-Identifier: GPL-2.0
obj-m := kpc2000.o
-kpc2000-objs += kp2000_module.o core.o cell_probe.o fileops.o
+kpc2000-objs += core.o cell_probe.o
#include <linux/types.h>
#include <linux/export.h>
#include <linux/slab.h>
-#include <asm/io.h>
#include <linux/io.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/mfd/core.h>
* D C2S DMA Present
* DDD C2S DMA Channel Number [up to 8 channels]
* II IRQ Count [0 to 3 IRQs per core]
- 1111111000
+ * 1111111000
* IIIIIII IRQ Base Number [up to 128 IRQs per card]
* ___ Spare
*
#define KP_CORE_ID_SPI 5
struct core_table_entry {
- u16 type;
- u32 offset;
- u32 length;
- bool s2c_dma_present;
- u8 s2c_dma_channel_num;
- bool c2s_dma_present;
- u8 c2s_dma_channel_num;
- u8 irq_count;
- u8 irq_base_num;
+ u16 type;
+ u32 offset;
+ u32 length;
+ bool s2c_dma_present;
+ u8 s2c_dma_channel_num;
+ bool c2s_dma_present;
+ u8 c2s_dma_channel_num;
+ u8 irq_count;
+ u8 irq_base_num;
};
static
void parse_core_table_entry_v0(struct core_table_entry *cte, const u64 read_val)
{
- cte->type = ((read_val & 0xFFF0000000000000) >> 52);
- cte->offset = ((read_val & 0x00000000FFFF0000) >> 16) * 4096;
- cte->length = ((read_val & 0x0000FFFF00000000) >> 32) * 8;
- cte->s2c_dma_present = ((read_val & 0x0008000000000000) >> 51);
- cte->s2c_dma_channel_num = ((read_val & 0x0007000000000000) >> 48);
- cte->c2s_dma_present = ((read_val & 0x0000000000008000) >> 15);
- cte->c2s_dma_channel_num = ((read_val & 0x0000000000007000) >> 12);
- cte->irq_count = ((read_val & 0x0000000000000C00) >> 10);
- cte->irq_base_num = ((read_val & 0x00000000000003F8) >> 3);
+ cte->type = ((read_val & 0xFFF0000000000000) >> 52);
+ cte->offset = ((read_val & 0x00000000FFFF0000) >> 16) * 4096;
+ cte->length = ((read_val & 0x0000FFFF00000000) >> 32) * 8;
+ cte->s2c_dma_present = ((read_val & 0x0008000000000000) >> 51);
+ cte->s2c_dma_channel_num = ((read_val & 0x0007000000000000) >> 48);
+ cte->c2s_dma_present = ((read_val & 0x0000000000008000) >> 15);
+ cte->c2s_dma_channel_num = ((read_val & 0x0000000000007000) >> 12);
+ cte->irq_count = ((read_val & 0x0000000000000C00) >> 10);
+ cte->irq_base_num = ((read_val & 0x00000000000003F8) >> 3);
}
static
void dbg_cte(struct kp2000_device *pcard, struct core_table_entry *cte)
{
- dev_dbg(&pcard->pdev->dev, "CTE: type:%3d offset:%3d (%3d) length:%3d (%3d) s2c:%d c2s:%d irq_count:%d base_irq:%d\n",
- cte->type,
- cte->offset,
- cte->offset / 4096,
- cte->length,
- cte->length / 8,
- (cte->s2c_dma_present ? cte->s2c_dma_channel_num : -1),
- (cte->c2s_dma_present ? cte->c2s_dma_channel_num : -1),
- cte->irq_count,
- cte->irq_base_num
- );
+ dev_dbg(&pcard->pdev->dev, "CTE: type:%3d offset:%3d (%3d) length:%3d (%3d) s2c:%d c2s:%d irq_count:%d base_irq:%d\n",
+ cte->type,
+ cte->offset,
+ cte->offset / 4096,
+ cte->length,
+ cte->length / 8,
+ (cte->s2c_dma_present ? cte->s2c_dma_channel_num : -1),
+ (cte->c2s_dma_present ? cte->c2s_dma_channel_num : -1),
+ cte->irq_count,
+ cte->irq_base_num
+ );
}
static
void parse_core_table_entry(struct core_table_entry *cte, const u64 read_val, const u8 entry_rev)
{
switch (entry_rev) {
- case 0: parse_core_table_entry_v0(cte, read_val); break;
- default: cte->type = 0; break;
+ case 0:
+ parse_core_table_entry_v0(cte, read_val);
+ break;
+ default:
+ cte->type = 0;
+ break;
}
}
-
-int probe_core_basic(unsigned int core_num, struct kp2000_device *pcard, char *name, const struct core_table_entry cte)
+static int probe_core_basic(unsigned int core_num, struct kp2000_device *pcard,
+ char *name, const struct core_table_entry cte)
{
- struct mfd_cell cell = {0};
- struct resource resources[2];
-
- struct kpc_core_device_platdata core_pdata = {
- .card_id = pcard->card_id,
- .build_version = pcard->build_version,
- .hardware_revision = pcard->hardware_revision,
- .ssid = pcard->ssid,
- .ddna = pcard->ddna,
- };
-
- dev_dbg(&pcard->pdev->dev, "Found Basic core: type = %02d dma = %02x / %02x offset = 0x%x length = 0x%x (%d regs)\n", cte.type, KPC_OLD_S2C_DMA_CH_NUM(cte), KPC_OLD_C2S_DMA_CH_NUM(cte), cte.offset, cte.length, cte.length / 8);
-
-
- cell.platform_data = &core_pdata;
- cell.pdata_size = sizeof(struct kpc_core_device_platdata);
- cell.name = name;
- cell.id = core_num;
- cell.num_resources = 2;
-
- memset(&resources, 0, sizeof(resources));
-
- resources[0].start = cte.offset;
- resources[0].end = cte.offset + (cte.length - 1);
- resources[0].flags = IORESOURCE_MEM;
-
- resources[1].start = pcard->pdev->irq;
- resources[1].end = pcard->pdev->irq;
- resources[1].flags = IORESOURCE_IRQ;
-
- cell.resources = resources;
-
- return mfd_add_devices(
- PCARD_TO_DEV(pcard), // parent
- pcard->card_num * 100, // id
- &cell, // struct mfd_cell *
- 1, // ndevs
- &pcard->regs_base_resource,
- 0, // irq_base
- NULL // struct irq_domain *
- );
+ struct mfd_cell cell = { .id = core_num, .name = name };
+ struct resource resources[2];
+
+ struct kpc_core_device_platdata core_pdata = {
+ .card_id = pcard->card_id,
+ .build_version = pcard->build_version,
+ .hardware_revision = pcard->hardware_revision,
+ .ssid = pcard->ssid,
+ .ddna = pcard->ddna,
+ };
+
+ dev_dbg(&pcard->pdev->dev, "Found Basic core: type = %02d dma = %02x / %02x offset = 0x%x length = 0x%x (%d regs)\n", cte.type, KPC_OLD_S2C_DMA_CH_NUM(cte), KPC_OLD_C2S_DMA_CH_NUM(cte), cte.offset, cte.length, cte.length / 8);
+
+ cell.platform_data = &core_pdata;
+ cell.pdata_size = sizeof(struct kpc_core_device_platdata);
+ cell.num_resources = 2;
+
+ memset(&resources, 0, sizeof(resources));
+
+ resources[0].start = cte.offset;
+ resources[0].end = cte.offset + (cte.length - 1);
+ resources[0].flags = IORESOURCE_MEM;
+
+ resources[1].start = pcard->pdev->irq;
+ resources[1].end = pcard->pdev->irq;
+ resources[1].flags = IORESOURCE_IRQ;
+
+ cell.resources = resources;
+
+ return mfd_add_devices(PCARD_TO_DEV(pcard), // parent
+ pcard->card_num * 100, // id
+ &cell, // struct mfd_cell *
+ 1, // ndevs
+ &pcard->regs_base_resource,
+ 0, // irq_base
+ NULL); // struct irq_domain *
}
-
struct kpc_uio_device {
- struct list_head list;
- struct kp2000_device *pcard;
- struct device *dev;
- struct uio_info uioinfo;
- struct core_table_entry cte;
- u16 core_num;
+ struct list_head list;
+ struct kp2000_device *pcard;
+ struct device *dev;
+ struct uio_info uioinfo;
+ struct core_table_entry cte;
+ u16 core_num;
};
-static ssize_t show_attr(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t offset_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct kpc_uio_device *kudev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", kudev->cte.offset);
+}
+static DEVICE_ATTR_RO(offset);
+
+static ssize_t size_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct kpc_uio_device *kudev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", kudev->cte.length);
+}
+static DEVICE_ATTR_RO(size);
+
+static ssize_t type_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct kpc_uio_device *kudev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", kudev->cte.type);
+}
+static DEVICE_ATTR_RO(type);
+
+static ssize_t s2c_dma_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct kpc_uio_device *kudev = dev_get_drvdata(dev);
+
+ if (!kudev->cte.s2c_dma_present)
+ return sprintf(buf, "%s", "not present\n");
+
+ return sprintf(buf, "%u\n", kudev->cte.s2c_dma_channel_num);
+}
+static DEVICE_ATTR_RO(s2c_dma);
+
+static ssize_t c2s_dma_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct kpc_uio_device *kudev = dev_get_drvdata(dev);
+
+ if (!kudev->cte.c2s_dma_present)
+ return sprintf(buf, "%s", "not present\n");
+
+ return sprintf(buf, "%u\n", kudev->cte.c2s_dma_channel_num);
+}
+static DEVICE_ATTR_RO(c2s_dma);
+
+static ssize_t irq_count_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- struct kpc_uio_device *kudev = dev_get_drvdata(dev);
-
- #define ATTR_NAME_CMP(v) (strcmp(v, attr->attr.name) == 0)
- if ATTR_NAME_CMP("offset"){
- return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.offset);
- } else if ATTR_NAME_CMP("size"){
- return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.length);
- } else if ATTR_NAME_CMP("type"){
- return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.type);
- }
- else if ATTR_NAME_CMP("s2c_dma"){
- if (kudev->cte.s2c_dma_present){
- return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.s2c_dma_channel_num);
- } else {
- return scnprintf(buf, PAGE_SIZE, "not present\n");
- }
- } else if ATTR_NAME_CMP("c2s_dma"){
- if (kudev->cte.c2s_dma_present){
- return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.c2s_dma_channel_num);
- } else {
- return scnprintf(buf, PAGE_SIZE, "not present\n");
- }
- }
- else if ATTR_NAME_CMP("irq_count"){
- return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.irq_count);
- } else if ATTR_NAME_CMP("irq_base_num"){
- return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->cte.irq_base_num);
- } else if ATTR_NAME_CMP("core_num"){
- return scnprintf(buf, PAGE_SIZE, "%u\n", kudev->core_num);
- } else {
- return 0;
- }
- #undef ATTR_NAME_CMP
+ struct kpc_uio_device *kudev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", kudev->cte.irq_count);
+}
+static DEVICE_ATTR_RO(irq_count);
+
+static ssize_t irq_base_num_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct kpc_uio_device *kudev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", kudev->cte.irq_base_num);
}
+static DEVICE_ATTR_RO(irq_base_num);
+
+static ssize_t core_num_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct kpc_uio_device *kudev = dev_get_drvdata(dev);
+ return sprintf(buf, "%u\n", kudev->core_num);
+}
+static DEVICE_ATTR_RO(core_num);
-DEVICE_ATTR(offset, 0444, show_attr, NULL);
-DEVICE_ATTR(size, 0444, show_attr, NULL);
-DEVICE_ATTR(type, 0444, show_attr, NULL);
-DEVICE_ATTR(s2c_dma_ch, 0444, show_attr, NULL);
-DEVICE_ATTR(c2s_dma_ch, 0444, show_attr, NULL);
-DEVICE_ATTR(s2c_dma, 0444, show_attr, NULL);
-DEVICE_ATTR(c2s_dma, 0444, show_attr, NULL);
-DEVICE_ATTR(irq_count, 0444, show_attr, NULL);
-DEVICE_ATTR(irq_base_num, 0444, show_attr, NULL);
-DEVICE_ATTR(core_num, 0444, show_attr, NULL);
-struct attribute * kpc_uio_class_attrs[] = {
+struct attribute *kpc_uio_class_attrs[] = {
&dev_attr_offset.attr,
&dev_attr_size.attr,
&dev_attr_type.attr,
- &dev_attr_s2c_dma_ch.attr,
- &dev_attr_c2s_dma_ch.attr,
&dev_attr_s2c_dma.attr,
&dev_attr_c2s_dma.attr,
&dev_attr_irq_count.attr,
NULL,
};
-
static
int kp2000_check_uio_irq(struct kp2000_device *pcard, u32 irq_num)
{
- u64 interrupt_active = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE);
- u64 interrupt_mask_inv = ~readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK);
- u64 irq_check_mask = (1 << irq_num);
- if (interrupt_active & irq_check_mask){ // if it's active (interrupt pending)
- if (interrupt_mask_inv & irq_check_mask){ // and if it's not masked off
- return 1;
- }
- }
- return 0;
+ u64 interrupt_active = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE);
+ u64 interrupt_mask_inv = ~readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK);
+ u64 irq_check_mask = (1 << irq_num);
+
+ if (interrupt_active & irq_check_mask) { // if it's active (interrupt pending)
+ if (interrupt_mask_inv & irq_check_mask) { // and if it's not masked off
+ return 1;
+ }
+ }
+ return 0;
}
static
irqreturn_t kuio_handler(int irq, struct uio_info *uioinfo)
{
- struct kpc_uio_device *kudev = uioinfo->priv;
- if (irq != kudev->pcard->pdev->irq)
- return IRQ_NONE;
-
- if (kp2000_check_uio_irq(kudev->pcard, kudev->cte.irq_base_num)){
- writeq((1 << kudev->cte.irq_base_num), kudev->pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); // Clear the active flag
- return IRQ_HANDLED;
- }
- return IRQ_NONE;
+ struct kpc_uio_device *kudev = uioinfo->priv;
+
+ if (irq != kudev->pcard->pdev->irq)
+ return IRQ_NONE;
+
+ if (kp2000_check_uio_irq(kudev->pcard, kudev->cte.irq_base_num)) {
+ writeq((1 << kudev->cte.irq_base_num), kudev->pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE); // Clear the active flag
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
}
static
int kuio_irqcontrol(struct uio_info *uioinfo, s32 irq_on)
{
- struct kpc_uio_device *kudev = uioinfo->priv;
- struct kp2000_device *pcard = kudev->pcard;
- u64 mask;
-
- lock_card(pcard);
- mask = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK);
- if (irq_on){
- mask &= ~(1 << (kudev->cte.irq_base_num));
- } else {
- mask |= (1 << (kudev->cte.irq_base_num));
- }
- writeq(mask, pcard->sysinfo_regs_base + REG_INTERRUPT_MASK);
- unlock_card(pcard);
-
- return 0;
+ struct kpc_uio_device *kudev = uioinfo->priv;
+ struct kp2000_device *pcard = kudev->pcard;
+ u64 mask;
+
+ mutex_lock(&pcard->sem);
+ mask = readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK);
+ if (irq_on)
+ mask &= ~(1 << (kudev->cte.irq_base_num));
+ else
+ mask |= (1 << (kudev->cte.irq_base_num));
+ writeq(mask, pcard->sysinfo_regs_base + REG_INTERRUPT_MASK);
+ mutex_unlock(&pcard->sem);
+
+ return 0;
}
-int probe_core_uio(unsigned int core_num, struct kp2000_device *pcard, char *name, const struct core_table_entry cte)
+static int probe_core_uio(unsigned int core_num, struct kp2000_device *pcard,
+ char *name, const struct core_table_entry cte)
{
- struct kpc_uio_device *kudev;
- int rv;
-
- dev_dbg(&pcard->pdev->dev, "Found UIO core: type = %02d dma = %02x / %02x offset = 0x%x length = 0x%x (%d regs)\n", cte.type, KPC_OLD_S2C_DMA_CH_NUM(cte), KPC_OLD_C2S_DMA_CH_NUM(cte), cte.offset, cte.length, cte.length / 8);
-
- kudev = kzalloc(sizeof(struct kpc_uio_device), GFP_KERNEL);
- if (!kudev){
- dev_err(&pcard->pdev->dev, "probe_core_uio: failed to kzalloc kpc_uio_device\n");
- return -ENOMEM;
- }
-
- INIT_LIST_HEAD(&kudev->list);
- kudev->pcard = pcard;
- kudev->cte = cte;
- kudev->core_num = core_num;
-
- kudev->uioinfo.priv = kudev;
- kudev->uioinfo.name = name;
- kudev->uioinfo.version = "0.0";
- if (cte.irq_count > 0){
- kudev->uioinfo.irq_flags = IRQF_SHARED;
- kudev->uioinfo.irq = pcard->pdev->irq;
- kudev->uioinfo.handler = kuio_handler;
- kudev->uioinfo.irqcontrol = kuio_irqcontrol;
- } else {
- kudev->uioinfo.irq = 0;
- }
-
- kudev->uioinfo.mem[0].name = "uiomap";
- kudev->uioinfo.mem[0].addr = pci_resource_start(pcard->pdev, REG_BAR) + cte.offset;
- kudev->uioinfo.mem[0].size = (cte.length + PAGE_SIZE-1) & ~(PAGE_SIZE-1); // Round up to nearest PAGE_SIZE boundary
- kudev->uioinfo.mem[0].memtype = UIO_MEM_PHYS;
-
- kudev->dev = device_create(kpc_uio_class, &pcard->pdev->dev, MKDEV(0,0), kudev, "%s.%d.%d.%d", kudev->uioinfo.name, pcard->card_num, cte.type, kudev->core_num);
- if (IS_ERR(kudev->dev)) {
- dev_err(&pcard->pdev->dev, "probe_core_uio device_create failed!\n");
- return -ENODEV;
- }
- dev_set_drvdata(kudev->dev, kudev);
-
- rv = uio_register_device(kudev->dev, &kudev->uioinfo);
- if (rv){
- dev_err(&pcard->pdev->dev, "probe_core_uio failed uio_register_device: %d\n", rv);
- return rv;
- }
-
- list_add_tail(&kudev->list, &pcard->uio_devices_list);
-
- return 0;
-}
+ struct kpc_uio_device *kudev;
+ int rv;
+
+ dev_dbg(&pcard->pdev->dev, "Found UIO core: type = %02d dma = %02x / %02x offset = 0x%x length = 0x%x (%d regs)\n", cte.type, KPC_OLD_S2C_DMA_CH_NUM(cte), KPC_OLD_C2S_DMA_CH_NUM(cte), cte.offset, cte.length, cte.length / 8);
+
+ kudev = kzalloc(sizeof(*kudev), GFP_KERNEL);
+ if (!kudev)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&kudev->list);
+ kudev->pcard = pcard;
+ kudev->cte = cte;
+ kudev->core_num = core_num;
+
+ kudev->uioinfo.priv = kudev;
+ kudev->uioinfo.name = name;
+ kudev->uioinfo.version = "0.0";
+ if (cte.irq_count > 0) {
+ kudev->uioinfo.irq_flags = IRQF_SHARED;
+ kudev->uioinfo.irq = pcard->pdev->irq;
+ kudev->uioinfo.handler = kuio_handler;
+ kudev->uioinfo.irqcontrol = kuio_irqcontrol;
+ } else {
+ kudev->uioinfo.irq = 0;
+ }
+
+ kudev->uioinfo.mem[0].name = "uiomap";
+ kudev->uioinfo.mem[0].addr = pci_resource_start(pcard->pdev, REG_BAR) + cte.offset;
+ kudev->uioinfo.mem[0].size = (cte.length + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); // Round up to nearest PAGE_SIZE boundary
+ kudev->uioinfo.mem[0].memtype = UIO_MEM_PHYS;
+
+ kudev->dev = device_create(kpc_uio_class, &pcard->pdev->dev, MKDEV(0, 0), kudev, "%s.%d.%d.%d", kudev->uioinfo.name, pcard->card_num, cte.type, kudev->core_num);
+ if (IS_ERR(kudev->dev)) {
+ dev_err(&pcard->pdev->dev, "%s: device_create failed!\n",
+ __func__);
+ kfree(kudev);
+ return -ENODEV;
+ }
+ dev_set_drvdata(kudev->dev, kudev);
+
+ rv = uio_register_device(kudev->dev, &kudev->uioinfo);
+ if (rv) {
+ dev_err(&pcard->pdev->dev, "%s: failed uio_register_device: %d\n",
+ __func__, rv);
+ put_device(kudev->dev);
+ kfree(kudev);
+ return rv;
+ }
+ list_add_tail(&kudev->list, &pcard->uio_devices_list);
+
+ return 0;
+}
static int create_dma_engine_core(struct kp2000_device *pcard, size_t engine_regs_offset, int engine_num, int irq_num)
{
- struct mfd_cell cell = {0};
- struct resource resources[2];
-
- dev_dbg(&pcard->pdev->dev, "create_dma_core(pcard = [%p], engine_regs_offset = %zx, engine_num = %d)\n", pcard, engine_regs_offset, engine_num);
-
- cell.platform_data = NULL;
- cell.pdata_size = 0;
- cell.id = engine_num;
- cell.name = KP_DRIVER_NAME_DMA_CONTROLLER;
- cell.num_resources = 2;
-
- memset(&resources, 0, sizeof(resources));
-
- resources[0].start = engine_regs_offset;
- resources[0].end = engine_regs_offset + (KPC_DMA_ENGINE_SIZE - 1);
- resources[0].flags = IORESOURCE_MEM;
-
- resources[1].start = irq_num;
- resources[1].end = irq_num;
- resources[1].flags = IORESOURCE_IRQ;
-
- cell.resources = resources;
-
- return mfd_add_devices(
- PCARD_TO_DEV(pcard), // parent
- pcard->card_num * 100, // id
- &cell, // struct mfd_cell *
- 1, // ndevs
- &pcard->dma_base_resource,
- 0, // irq_base
- NULL // struct irq_domain *
- );
+ struct mfd_cell cell = { .id = engine_num };
+ struct resource resources[2];
+
+ dev_dbg(&pcard->pdev->dev, "create_dma_core(pcard = [%p], engine_regs_offset = %zx, engine_num = %d)\n", pcard, engine_regs_offset, engine_num);
+
+ cell.platform_data = NULL;
+ cell.pdata_size = 0;
+ cell.name = KP_DRIVER_NAME_DMA_CONTROLLER;
+ cell.num_resources = 2;
+
+ memset(&resources, 0, sizeof(resources));
+
+ resources[0].start = engine_regs_offset;
+ resources[0].end = engine_regs_offset + (KPC_DMA_ENGINE_SIZE - 1);
+ resources[0].flags = IORESOURCE_MEM;
+
+ resources[1].start = irq_num;
+ resources[1].end = irq_num;
+ resources[1].flags = IORESOURCE_IRQ;
+
+ cell.resources = resources;
+
+ return mfd_add_devices(PCARD_TO_DEV(pcard), // parent
+ pcard->card_num * 100, // id
+ &cell, // struct mfd_cell *
+ 1, // ndevs
+ &pcard->dma_base_resource,
+ 0, // irq_base
+ NULL); // struct irq_domain *
}
static int kp2000_setup_dma_controller(struct kp2000_device *pcard)
{
- int err;
- unsigned int i;
- u64 capabilities_reg;
-
- // S2C Engines
- for (i = 0 ; i < 32 ; i++){
- capabilities_reg = readq( pcard->dma_bar_base + KPC_DMA_S2C_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i) );
- if (capabilities_reg & ENGINE_CAP_PRESENT_MASK){
- err = create_dma_engine_core(pcard, (KPC_DMA_S2C_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i)), i, pcard->pdev->irq);
- if (err) goto err_out;
- }
- }
- // C2S Engines
- for (i = 0 ; i < 32 ; i++){
- capabilities_reg = readq( pcard->dma_bar_base + KPC_DMA_C2S_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i) );
- if (capabilities_reg & ENGINE_CAP_PRESENT_MASK){
- err = create_dma_engine_core(pcard, (KPC_DMA_C2S_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i)), 32+i, pcard->pdev->irq);
- if (err) goto err_out;
- }
- }
-
- return 0;
-
+ int err;
+ unsigned int i;
+ u64 capabilities_reg;
+
+ // S2C Engines
+ for (i = 0 ; i < 32 ; i++) {
+ capabilities_reg = readq(pcard->dma_bar_base + KPC_DMA_S2C_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i));
+ if (capabilities_reg & ENGINE_CAP_PRESENT_MASK) {
+ err = create_dma_engine_core(pcard, (KPC_DMA_S2C_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i)), i, pcard->pdev->irq);
+ if (err)
+ goto err_out;
+ }
+ }
+ // C2S Engines
+ for (i = 0 ; i < 32 ; i++) {
+ capabilities_reg = readq(pcard->dma_bar_base + KPC_DMA_C2S_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i));
+ if (capabilities_reg & ENGINE_CAP_PRESENT_MASK) {
+ err = create_dma_engine_core(pcard, (KPC_DMA_C2S_BASE_OFFSET + (KPC_DMA_ENGINE_SIZE * i)), 32 + i, pcard->pdev->irq);
+ if (err)
+ goto err_out;
+ }
+ }
+
+ return 0;
+
err_out:
- dev_err(&pcard->pdev->dev, "kp2000_setup_dma_controller: failed to add a DMA Engine: %d\n", err);
- return err;
+ dev_err(&pcard->pdev->dev, "%s: failed to add a DMA Engine: %d\n",
+ __func__, err);
+ return err;
}
int kp2000_probe_cores(struct kp2000_device *pcard)
{
- int err = 0;
- int i;
- int current_type_id;
- u64 read_val;
- unsigned int highest_core_id = 0;
- struct core_table_entry cte;
-
- dev_dbg(&pcard->pdev->dev, "kp2000_probe_cores(pcard = %p / %d)\n", pcard, pcard->card_num);
-
- err = kp2000_setup_dma_controller(pcard);
- if (err) return err;
-
- INIT_LIST_HEAD(&pcard->uio_devices_list);
-
- // First, iterate the core table looking for the highest CORE_ID
- for (i = 0 ; i < pcard->core_table_length ; i++){
- read_val = readq(pcard->sysinfo_regs_base + ((pcard->core_table_offset + i) * 8));
- parse_core_table_entry(&cte, read_val, pcard->core_table_rev);
- dbg_cte(pcard, &cte);
- if (cte.type > highest_core_id){
- highest_core_id = cte.type;
- }
- if (cte.type == KP_CORE_ID_INVALID){
- dev_info(&pcard->pdev->dev, "Found Invalid core: %016llx\n", read_val);
- }
- }
- // Then, iterate over the possible core types.
- for (current_type_id = 1 ; current_type_id <= highest_core_id ; current_type_id++){
- unsigned int core_num = 0;
- // Foreach core type, iterate the whole table and instantiate subdevices for each core.
- // Yes, this is O(n*m) but the actual runtime is small enough that it's an acceptable tradeoff.
- for (i = 0 ; i < pcard->core_table_length ; i++){
- read_val = readq(pcard->sysinfo_regs_base + ((pcard->core_table_offset + i) * 8));
- parse_core_table_entry(&cte, read_val, pcard->core_table_rev);
-
- if (cte.type == current_type_id){
- switch (cte.type){
- case KP_CORE_ID_I2C:
- err = probe_core_basic(core_num, pcard, KP_DRIVER_NAME_I2C, cte);
- break;
-
- case KP_CORE_ID_SPI:
- err = probe_core_basic(core_num, pcard, KP_DRIVER_NAME_SPI, cte);
- break;
-
- default:
- err = probe_core_uio(core_num, pcard, "kpc_uio", cte);
- break;
- }
- if (err){
- dev_err(&pcard->pdev->dev, "kp2000_probe_cores: failed to add core %d: %d\n", i, err);
- return err;
- }
- core_num++;
- }
- }
- }
-
- // Finally, instantiate a UIO device for the core_table.
- cte.type = 0; // CORE_ID_BOARD_INFO
- cte.offset = 0; // board info is always at the beginning
- cte.length = 512*8;
- cte.s2c_dma_present = false;
- cte.s2c_dma_channel_num = 0;
- cte.c2s_dma_present = false;
- cte.c2s_dma_channel_num = 0;
- cte.irq_count = 0;
- cte.irq_base_num = 0;
- err = probe_core_uio(0, pcard, "kpc_uio", cte);
- if (err){
- dev_err(&pcard->pdev->dev, "kp2000_probe_cores: failed to add board_info core: %d\n", err);
- return err;
- }
-
- return 0;
+ int err = 0;
+ int i;
+ int current_type_id;
+ u64 read_val;
+ unsigned int highest_core_id = 0;
+ struct core_table_entry cte;
+
+ dev_dbg(&pcard->pdev->dev, "%s(pcard = %p / %d)\n", __func__, pcard,
+ pcard->card_num);
+
+ err = kp2000_setup_dma_controller(pcard);
+ if (err)
+ return err;
+
+ INIT_LIST_HEAD(&pcard->uio_devices_list);
+
+ // First, iterate the core table looking for the highest CORE_ID
+ for (i = 0 ; i < pcard->core_table_length ; i++) {
+ read_val = readq(pcard->sysinfo_regs_base + ((pcard->core_table_offset + i) * 8));
+ parse_core_table_entry(&cte, read_val, pcard->core_table_rev);
+ dbg_cte(pcard, &cte);
+ if (cte.type > highest_core_id)
+ highest_core_id = cte.type;
+ if (cte.type == KP_CORE_ID_INVALID)
+ dev_info(&pcard->pdev->dev, "Found Invalid core: %016llx\n", read_val);
+ }
+ // Then, iterate over the possible core types.
+ for (current_type_id = 1 ; current_type_id <= highest_core_id ; current_type_id++) {
+ unsigned int core_num = 0;
+ // Foreach core type, iterate the whole table and instantiate subdevices for each core.
+ // Yes, this is O(n*m) but the actual runtime is small enough that it's an acceptable tradeoff.
+ for (i = 0 ; i < pcard->core_table_length ; i++) {
+ read_val = readq(pcard->sysinfo_regs_base + ((pcard->core_table_offset + i) * 8));
+ parse_core_table_entry(&cte, read_val, pcard->core_table_rev);
+
+ if (cte.type != current_type_id)
+ continue;
+
+ switch (cte.type) {
+ case KP_CORE_ID_I2C:
+ err = probe_core_basic(core_num, pcard,
+ KP_DRIVER_NAME_I2C, cte);
+ break;
+
+ case KP_CORE_ID_SPI:
+ err = probe_core_basic(core_num, pcard,
+ KP_DRIVER_NAME_SPI, cte);
+ break;
+
+ default:
+ err = probe_core_uio(core_num, pcard, "kpc_uio", cte);
+ break;
+ }
+ if (err) {
+ dev_err(&pcard->pdev->dev,
+ "%s: failed to add core %d: %d\n",
+ __func__, i, err);
+ goto error;
+ }
+ core_num++;
+ }
+ }
+
+ // Finally, instantiate a UIO device for the core_table.
+ cte.type = 0; // CORE_ID_BOARD_INFO
+ cte.offset = 0; // board info is always at the beginning
+ cte.length = 512 * 8;
+ cte.s2c_dma_present = false;
+ cte.s2c_dma_channel_num = 0;
+ cte.c2s_dma_present = false;
+ cte.c2s_dma_channel_num = 0;
+ cte.irq_count = 0;
+ cte.irq_base_num = 0;
+ err = probe_core_uio(0, pcard, "kpc_uio", cte);
+ if (err) {
+ dev_err(&pcard->pdev->dev, "%s: failed to add board_info core: %d\n",
+ __func__, err);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ kp2000_remove_cores(pcard);
+ mfd_remove_devices(PCARD_TO_DEV(pcard));
+ return err;
}
void kp2000_remove_cores(struct kp2000_device *pcard)
{
- struct list_head *ptr;
- struct list_head *next;
- list_for_each_safe(ptr, next, &pcard->uio_devices_list){
- struct kpc_uio_device *kudev = list_entry(ptr, struct kpc_uio_device, list);
- uio_unregister_device(&kudev->uioinfo);
- device_unregister(kudev->dev);
- list_del(&kudev->list);
- kfree(kudev);
- }
+ struct list_head *ptr;
+ struct list_head *next;
+
+ list_for_each_safe(ptr, next, &pcard->uio_devices_list) {
+ struct kpc_uio_device *kudev = list_entry(ptr, struct kpc_uio_device, list);
+
+ uio_unregister_device(&kudev->uioinfo);
+ device_unregister(kudev->dev);
+ list_del(&kudev->list);
+ kfree(kudev);
+ }
}
// SPDX-License-Identifier: GPL-2.0+
+#include <linux/kernel.h>
+#include <linux/idr.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/types.h>
#include <linux/export.h>
#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/cdev.h>
+#include <linux/rwsem.h>
+#include <linux/uaccess.h>
#include <asm/io.h>
#include <linux/io.h>
#include <linux/mfd/core.h>
#include <linux/sched.h>
#include <linux/jiffies.h>
#include "pcie.h"
+#include "uapi.h"
+static DEFINE_IDA(card_num_ida);
/*******************************************************
- * SysFS Attributes
- ******************************************************/
-static ssize_t show_attr(struct device *dev, struct device_attribute *attr, char *buf)
+ * SysFS Attributes
+ ******************************************************/
+
+static ssize_t ssid_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct kp2000_device *pcard;
-
- if (!pdev) return -ENXIO;
- pcard = pci_get_drvdata(pdev);
- if (!pcard) return -ENXIO;
-
- if (strcmp("ssid", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%016llx\n", pcard->ssid); } else
- if (strcmp("ddna", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%016llx\n", pcard->ddna); } else
- if (strcmp("card_id", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%08x\n", pcard->card_id); } else
- if (strcmp("hw_rev", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%08x\n", pcard->hardware_revision); } else
- if (strcmp("build", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%08x\n", pcard->build_version); } else
- if (strcmp("build_date", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%08x\n", pcard->build_datestamp); } else
- if (strcmp("build_time", attr->attr.name) == 0){ return scnprintf(buf, PAGE_SIZE, "%08x\n", pcard->build_timestamp); } else
- { return -ENXIO; }
+ struct kp2000_device *pcard = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%016llx\n", pcard->ssid);
}
+static DEVICE_ATTR_RO(ssid);
-static ssize_t show_cpld_config_reg(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t ddna_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct kp2000_device *pcard;
- u64 val;
+ struct kp2000_device *pcard = dev_get_drvdata(dev);
- if (!pdev)
- return -ENXIO;
+ return sprintf(buf, "%016llx\n", pcard->ddna);
+}
+static DEVICE_ATTR_RO(ddna);
- pcard = pci_get_drvdata(pdev);
- if (!pcard)
- return -ENXIO;
+static ssize_t card_id_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct kp2000_device *pcard = dev_get_drvdata(dev);
- val = readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG);
- return scnprintf(buf, PAGE_SIZE, "%016llx\n", val);
+ return sprintf(buf, "%08x\n", pcard->card_id);
+}
+static DEVICE_ATTR_RO(card_id);
+
+static ssize_t hw_rev_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct kp2000_device *pcard = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%08x\n", pcard->hardware_revision);
}
-static ssize_t cpld_reconfigure(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static DEVICE_ATTR_RO(hw_rev);
+
+static ssize_t build_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- struct pci_dev *pdev = to_pci_dev(dev);
- long wr_val;
- struct kp2000_device *pcard;
- int rv;
-
- if (!pdev) return -ENXIO;
- pcard = pci_get_drvdata(pdev);
- if (!pcard) return -ENXIO;
-
- rv = kstrtol(buf, 0, &wr_val);
- if (rv < 0) return rv;
- if (wr_val > 7) return -EINVAL;
-
- wr_val = wr_val << 8;
- wr_val |= 0x1; // Set the "Configure Go" bit
- writeq(wr_val, pcard->sysinfo_regs_base + REG_CPLD_CONFIG);
- return count;
+ struct kp2000_device *pcard = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%08x\n", pcard->build_version);
}
+static DEVICE_ATTR_RO(build);
+static ssize_t build_date_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct kp2000_device *pcard = dev_get_drvdata(dev);
-DEVICE_ATTR(ssid, 0444, show_attr, NULL);
-DEVICE_ATTR(ddna, 0444, show_attr, NULL);
-DEVICE_ATTR(card_id, 0444, show_attr, NULL);
-DEVICE_ATTR(hw_rev, 0444, show_attr, NULL);
-DEVICE_ATTR(build, 0444, show_attr, NULL);
-DEVICE_ATTR(build_date, 0444, show_attr, NULL);
-DEVICE_ATTR(build_time, 0444, show_attr, NULL);
-DEVICE_ATTR(cpld_reg, 0444, show_cpld_config_reg, NULL);
-DEVICE_ATTR(cpld_reconfigure, 0220, NULL, cpld_reconfigure);
-
-static const struct attribute * kp_attr_list[] = {
- &dev_attr_ssid.attr,
- &dev_attr_ddna.attr,
- &dev_attr_card_id.attr,
- &dev_attr_hw_rev.attr,
- &dev_attr_build.attr,
- &dev_attr_build_date.attr,
- &dev_attr_build_time.attr,
- &dev_attr_cpld_reg.attr,
- &dev_attr_cpld_reconfigure.attr,
- NULL,
-};
+ return sprintf(buf, "%08x\n", pcard->build_datestamp);
+}
+static DEVICE_ATTR_RO(build_date);
+
+static ssize_t build_time_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct kp2000_device *pcard = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%08x\n", pcard->build_timestamp);
+}
+static DEVICE_ATTR_RO(build_time);
+
+static ssize_t cpld_reg_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct kp2000_device *pcard = dev_get_drvdata(dev);
+ u64 val;
+
+ val = readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG);
+ return sprintf(buf, "%016llx\n", val);
+}
+static DEVICE_ATTR_RO(cpld_reg);
+
+static ssize_t cpld_reconfigure(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct kp2000_device *pcard = dev_get_drvdata(dev);
+ long wr_val;
+ int rv;
+
+ rv = kstrtol(buf, 0, &wr_val);
+ if (rv < 0)
+ return rv;
+ if (wr_val > 7)
+ return -EINVAL;
+
+ wr_val = wr_val << 8;
+ wr_val |= 0x1; // Set the "Configure Go" bit
+ writeq(wr_val, pcard->sysinfo_regs_base + REG_CPLD_CONFIG);
+ return count;
+}
+static DEVICE_ATTR(cpld_reconfigure, 0220, NULL, cpld_reconfigure);
+static const struct attribute *kp_attr_list[] = {
+ &dev_attr_ssid.attr,
+ &dev_attr_ddna.attr,
+ &dev_attr_card_id.attr,
+ &dev_attr_hw_rev.attr,
+ &dev_attr_build.attr,
+ &dev_attr_build_date.attr,
+ &dev_attr_build_time.attr,
+ &dev_attr_cpld_reg.attr,
+ &dev_attr_cpld_reconfigure.attr,
+ NULL,
+};
/*******************************************************
- * Functions
- ******************************************************/
+ * Functions
+ ******************************************************/
static void wait_and_read_ssid(struct kp2000_device *pcard)
{
- u64 read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID);
- unsigned long timeout;
-
- if (read_val & 0x8000000000000000){
- pcard->ssid = read_val;
- return;
- }
-
- timeout = jiffies + (HZ * 2);
- do {
- read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID);
- if (read_val & 0x8000000000000000){
- pcard->ssid = read_val;
- return;
- }
- cpu_relax();
- //schedule();
- } while (time_before(jiffies, timeout));
-
- dev_notice(&pcard->pdev->dev, "SSID didn't show up!\n");
-
- #if 0
- // Timed out waiting for the SSID to show up, just use the DDNA instead?
- read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_DDNA);
- pcard->ssid = read_val;
- #else
- // Timed out waiting for the SSID to show up, stick all zeros in the value
- pcard->ssid = 0;
- #endif
+ u64 read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID);
+ unsigned long timeout;
+
+ if (read_val & 0x8000000000000000) {
+ pcard->ssid = read_val;
+ return;
+ }
+
+ timeout = jiffies + (HZ * 2);
+ do {
+ read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID);
+ if (read_val & 0x8000000000000000) {
+ pcard->ssid = read_val;
+ return;
+ }
+ cpu_relax();
+ //schedule();
+ } while (time_before(jiffies, timeout));
+
+ dev_notice(&pcard->pdev->dev, "SSID didn't show up!\n");
+
+#if 0
+ // Timed out waiting for the SSID to show up, just use the DDNA instead?
+ read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_DDNA);
+ pcard->ssid = read_val;
+#else
+ // Timed out waiting for the SSID to show up, stick all zeros in the
+ // value
+ pcard->ssid = 0;
+#endif
}
static int read_system_regs(struct kp2000_device *pcard)
{
- u64 read_val;
-
- read_val = readq(pcard->sysinfo_regs_base + REG_MAGIC_NUMBER);
- if (read_val != KP2000_MAGIC_VALUE){
- dev_err(&pcard->pdev->dev, "Invalid magic! Got: 0x%016llx Want: 0x%016lx\n", read_val, KP2000_MAGIC_VALUE);
- return -EILSEQ;
- }
-
- read_val = readq(pcard->sysinfo_regs_base + REG_CARD_ID_AND_BUILD);
- pcard->card_id = (read_val & 0xFFFFFFFF00000000) >> 32;
- pcard->build_version = (read_val & 0x00000000FFFFFFFF) >> 0;
-
- read_val = readq(pcard->sysinfo_regs_base + REG_DATE_AND_TIME_STAMPS);
- pcard->build_datestamp = (read_val & 0xFFFFFFFF00000000) >> 32;
- pcard->build_timestamp = (read_val & 0x00000000FFFFFFFF) >> 0;
-
- read_val = readq(pcard->sysinfo_regs_base + REG_CORE_TABLE_OFFSET);
- pcard->core_table_length = (read_val & 0xFFFFFFFF00000000) >> 32;
- pcard->core_table_offset = (read_val & 0x00000000FFFFFFFF) >> 0;
-
- wait_and_read_ssid(pcard);
-
- read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_HW_ID);
- pcard->core_table_rev = (read_val & 0x0000000000000F00) >> 8;
- pcard->hardware_revision = (read_val & 0x000000000000001F);
-
- read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_DDNA);
- pcard->ddna = read_val;
-
- dev_info(&pcard->pdev->dev, "system_regs: %08x %08x %08x %08x %02x %d %d %016llx %016llx\n",
- pcard->card_id,
- pcard->build_version,
- pcard->build_datestamp,
- pcard->build_timestamp,
- pcard->hardware_revision,
- pcard->core_table_rev,
- pcard->core_table_length,
- pcard->ssid,
- pcard->ddna
- );
-
- if (pcard->core_table_rev > 1){
- dev_err(&pcard->pdev->dev, "core table entry revision is higher than we can deal with, cannot continue with this card!\n");
- return 1;
- }
-
- return 0;
+ u64 read_val;
+
+ read_val = readq(pcard->sysinfo_regs_base + REG_MAGIC_NUMBER);
+ if (read_val != KP2000_MAGIC_VALUE) {
+ dev_err(&pcard->pdev->dev,
+ "Invalid magic! Got: 0x%016llx Want: 0x%016lx\n",
+ read_val, KP2000_MAGIC_VALUE);
+ return -EILSEQ;
+ }
+
+ read_val = readq(pcard->sysinfo_regs_base + REG_CARD_ID_AND_BUILD);
+ pcard->card_id = (read_val & 0xFFFFFFFF00000000) >> 32;
+ pcard->build_version = (read_val & 0x00000000FFFFFFFF) >> 0;
+
+ read_val = readq(pcard->sysinfo_regs_base + REG_DATE_AND_TIME_STAMPS);
+ pcard->build_datestamp = (read_val & 0xFFFFFFFF00000000) >> 32;
+ pcard->build_timestamp = (read_val & 0x00000000FFFFFFFF) >> 0;
+
+ read_val = readq(pcard->sysinfo_regs_base + REG_CORE_TABLE_OFFSET);
+ pcard->core_table_length = (read_val & 0xFFFFFFFF00000000) >> 32;
+ pcard->core_table_offset = (read_val & 0x00000000FFFFFFFF) >> 0;
+
+ wait_and_read_ssid(pcard);
+
+ read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_HW_ID);
+ pcard->core_table_rev = (read_val & 0x0000000000000F00) >> 8;
+ pcard->hardware_revision = (read_val & 0x000000000000001F);
+
+ read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_DDNA);
+ pcard->ddna = read_val;
+
+ dev_info(&pcard->pdev->dev,
+ "system_regs: %08x %08x %08x %08x %02x %d %d %016llx %016llx\n",
+ pcard->card_id,
+ pcard->build_version,
+ pcard->build_datestamp,
+ pcard->build_timestamp,
+ pcard->hardware_revision,
+ pcard->core_table_rev,
+ pcard->core_table_length,
+ pcard->ssid,
+ pcard->ddna);
+
+ if (pcard->core_table_rev > 1) {
+ dev_err(&pcard->pdev->dev,
+ "core table entry revision is higher than we can deal with, cannot continue with this card!\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+static irqreturn_t kp2000_irq_handler(int irq, void *dev_id)
+{
+ struct kp2000_device *pcard = dev_id;
+
+ writel(KPC_DMA_CARD_IRQ_ENABLE |
+ KPC_DMA_CARD_USER_INTERRUPT_MODE |
+ KPC_DMA_CARD_USER_INTERRUPT_ACTIVE,
+ pcard->dma_common_regs);
+ return IRQ_HANDLED;
+}
+
+static int kp2000_cdev_open(struct inode *inode, struct file *filp)
+{
+ struct kp2000_device *pcard = container_of(filp->private_data, struct kp2000_device, miscdev);
+
+ dev_dbg(&pcard->pdev->dev, "kp2000_cdev_open(filp = [%p], pcard = [%p])\n", filp, pcard);
+
+ filp->private_data = pcard; /* so other methods can access it */
+
+ return 0;
+}
+
+static int kp2000_cdev_close(struct inode *inode, struct file *filp)
+{
+ struct kp2000_device *pcard = filp->private_data;
+
+ dev_dbg(&pcard->pdev->dev, "kp2000_cdev_close(filp = [%p], pcard = [%p])\n", filp, pcard);
+ return 0;
+}
+
+static ssize_t kp2000_cdev_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ struct kp2000_device *pcard = filp->private_data;
+ int cnt = 0;
+ int ret;
+#define BUFF_CNT 1024
+ char buff[BUFF_CNT] = {0}; //NOTE: Increase this so it is at least as large as all the scnprintfs. And don't use unbounded strings. "%s"
+ //NOTE: also, this is a really shitty way to implement the read() call, but it will work for any size 'count'.
+
+ if (WARN(NULL == buf, "kp2000_cdev_read: buf is a NULL pointer!\n"))
+ return -EINVAL;
+
+ cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Card ID : 0x%08x\n", pcard->card_id);
+ cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Build Version : 0x%08x\n", pcard->build_version);
+ cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Build Date : 0x%08x\n", pcard->build_datestamp);
+ cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Build Time : 0x%08x\n", pcard->build_timestamp);
+ cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Core Table Offset : 0x%08x\n", pcard->core_table_offset);
+ cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Core Table Length : 0x%08x\n", pcard->core_table_length);
+ cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Hardware Revision : 0x%08x\n", pcard->hardware_revision);
+ cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "SSID : 0x%016llx\n", pcard->ssid);
+ cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "DDNA : 0x%016llx\n", pcard->ddna);
+ cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "IRQ Mask : 0x%016llx\n", readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK));
+ cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "IRQ Active : 0x%016llx\n", readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE));
+ cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "CPLD : 0x%016llx\n", readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG));
+
+ if (*f_pos >= cnt)
+ return 0;
+
+ if (count > cnt)
+ count = cnt;
+
+ ret = copy_to_user(buf, buff + *f_pos, count);
+ if (ret)
+ return -EFAULT;
+ *f_pos += count;
+ return count;
}
-irqreturn_t kp2000_irq_handler(int irq, void *dev_id)
+static long kp2000_cdev_ioctl(struct file *filp, unsigned int ioctl_num,
+ unsigned long ioctl_param)
{
- struct kp2000_device *pcard = (struct kp2000_device*)dev_id;
- SetBackEndControl(pcard->dma_common_regs, KPC_DMA_CARD_IRQ_ENABLE | KPC_DMA_CARD_USER_INTERRUPT_MODE | KPC_DMA_CARD_USER_INTERRUPT_ACTIVE);
- return IRQ_HANDLED;
+ struct kp2000_device *pcard = filp->private_data;
+
+ dev_dbg(&pcard->pdev->dev, "kp2000_cdev_ioctl(filp = [%p], ioctl_num = 0x%08x, ioctl_param = 0x%016lx) pcard = [%p]\n", filp, ioctl_num, ioctl_param, pcard);
+
+ switch (ioctl_num){
+ case KP2000_IOCTL_GET_CPLD_REG: return readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG);
+ case KP2000_IOCTL_GET_PCIE_ERROR_REG: return readq(pcard->sysinfo_regs_base + REG_PCIE_ERROR_COUNT);
+
+ case KP2000_IOCTL_GET_EVERYTHING: {
+ struct kp2000_regs regs;
+ int ret;
+
+ memset(®s, 0, sizeof(regs));
+ regs.card_id = pcard->card_id;
+ regs.build_version = pcard->build_version;
+ regs.build_datestamp = pcard->build_datestamp;
+ regs.build_timestamp = pcard->build_timestamp;
+ regs.hw_rev = pcard->hardware_revision;
+ regs.ssid = pcard->ssid;
+ regs.ddna = pcard->ddna;
+ regs.cpld_reg = readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG);
+
+ ret = copy_to_user((void*)ioctl_param, (void*)®s, sizeof(regs));
+ if (ret)
+ return -EFAULT;
+
+ return sizeof(regs);
+ }
+
+ default:
+ return -ENOTTY;
+ }
+ return -ENOTTY;
+}
+
+static struct file_operations kp2000_fops = {
+ .owner = THIS_MODULE,
+ .open = kp2000_cdev_open,
+ .release = kp2000_cdev_close,
+ .read = kp2000_cdev_read,
+ .llseek = noop_llseek,
+ .unlocked_ioctl = kp2000_cdev_ioctl,
+};
+
+static int kp2000_pcie_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int err = 0;
+ struct kp2000_device *pcard;
+ int rv;
+ unsigned long reg_bar_phys_addr;
+ unsigned long reg_bar_phys_len;
+ unsigned long dma_bar_phys_addr;
+ unsigned long dma_bar_phys_len;
+ u16 regval;
+
+ dev_dbg(&pdev->dev, "kp2000_pcie_probe(pdev = [%p], id = [%p])\n",
+ pdev, id);
+
+ /*
+ * Step 1: Allocate a struct for the pcard
+ */
+ pcard = kzalloc(sizeof(struct kp2000_device), GFP_KERNEL);
+ if (NULL == pcard) {
+ dev_err(&pdev->dev,
+ "probe: failed to allocate private card data\n");
+ return -ENOMEM;
+ }
+ dev_dbg(&pdev->dev, "probe: allocated struct kp2000_device @ %p\n",
+ pcard);
+
+ /*
+ * Step 2: Initialize trivial pcard elements
+ */
+ err = ida_simple_get(&card_num_ida, 1, INT_MAX, GFP_KERNEL);
+ if (err < 0) {
+ dev_err(&pdev->dev, "probe: failed to get card number (%d)\n",
+ err);
+ goto out2;
+ }
+ pcard->card_num = err;
+ scnprintf(pcard->name, 16, "kpcard%u", pcard->card_num);
+
+ mutex_init(&pcard->sem);
+ mutex_lock(&pcard->sem);
+
+ pcard->pdev = pdev;
+ pci_set_drvdata(pdev, pcard);
+
+ /*
+ * Step 3: Enable PCI device
+ */
+ err = pci_enable_device(pcard->pdev);
+ if (err) {
+ dev_err(&pcard->pdev->dev,
+ "probe: failed to enable PCIE2000 PCIe device (%d)\n",
+ err);
+ goto out3;
+ }
+
+ /*
+ * Step 4: Setup the Register BAR
+ */
+ reg_bar_phys_addr = pci_resource_start(pcard->pdev, REG_BAR);
+ reg_bar_phys_len = pci_resource_len(pcard->pdev, REG_BAR);
+
+ pcard->regs_bar_base = ioremap_nocache(reg_bar_phys_addr, PAGE_SIZE);
+ if (NULL == pcard->regs_bar_base) {
+ dev_err(&pcard->pdev->dev,
+ "probe: REG_BAR could not remap memory to virtual space\n");
+ err = -ENODEV;
+ goto out4;
+ }
+ dev_dbg(&pcard->pdev->dev,
+ "probe: REG_BAR virt hardware address start [%p]\n",
+ pcard->regs_bar_base);
+
+ err = pci_request_region(pcard->pdev, REG_BAR, KP_DRIVER_NAME_KP2000);
+ if (err) {
+ iounmap(pcard->regs_bar_base);
+ dev_err(&pcard->pdev->dev,
+ "probe: failed to acquire PCI region (%d)\n",
+ err);
+ err = -ENODEV;
+ goto out4;
+ }
+
+ pcard->regs_base_resource.start = reg_bar_phys_addr;
+ pcard->regs_base_resource.end = reg_bar_phys_addr +
+ reg_bar_phys_len - 1;
+ pcard->regs_base_resource.flags = IORESOURCE_MEM;
+
+ /*
+ * Step 5: Setup the DMA BAR
+ */
+ dma_bar_phys_addr = pci_resource_start(pcard->pdev, DMA_BAR);
+ dma_bar_phys_len = pci_resource_len(pcard->pdev, DMA_BAR);
+
+ pcard->dma_bar_base = ioremap_nocache(dma_bar_phys_addr,
+ dma_bar_phys_len);
+ if (NULL == pcard->dma_bar_base) {
+ dev_err(&pcard->pdev->dev,
+ "probe: DMA_BAR could not remap memory to virtual space\n");
+ err = -ENODEV;
+ goto out5;
+ }
+ dev_dbg(&pcard->pdev->dev,
+ "probe: DMA_BAR virt hardware address start [%p]\n",
+ pcard->dma_bar_base);
+
+ pcard->dma_common_regs = pcard->dma_bar_base + KPC_DMA_COMMON_OFFSET;
+
+ err = pci_request_region(pcard->pdev, DMA_BAR, "kp2000_pcie");
+ if (err) {
+ iounmap(pcard->dma_bar_base);
+ dev_err(&pcard->pdev->dev,
+ "probe: failed to acquire PCI region (%d)\n", err);
+ err = -ENODEV;
+ goto out5;
+ }
+
+ pcard->dma_base_resource.start = dma_bar_phys_addr;
+ pcard->dma_base_resource.end = dma_bar_phys_addr +
+ dma_bar_phys_len - 1;
+ pcard->dma_base_resource.flags = IORESOURCE_MEM;
+
+ /*
+ * Step 6: System Regs
+ */
+ pcard->sysinfo_regs_base = pcard->regs_bar_base;
+ err = read_system_regs(pcard);
+ if (err)
+ goto out6;
+
+ // Disable all "user" interrupts because they're not used yet.
+ writeq(0xFFFFFFFFFFFFFFFF,
+ pcard->sysinfo_regs_base + REG_INTERRUPT_MASK);
+
+ /*
+ * Step 7: Configure PCI thingies
+ */
+ // let the card master PCIe
+ pci_set_master(pcard->pdev);
+ // enable IO and mem if not already done
+ pci_read_config_word(pcard->pdev, PCI_COMMAND, ®val);
+ regval |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+ pci_write_config_word(pcard->pdev, PCI_COMMAND, regval);
+
+ // Clear relaxed ordering bit
+ pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL,
+ PCI_EXP_DEVCTL_RELAX_EN, 0);
+
+ // Set Max_Payload_Size and Max_Read_Request_Size
+ regval = (0x0) << 5; // Max_Payload_Size = 128 B
+ pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL,
+ PCI_EXP_DEVCTL_PAYLOAD, regval);
+ regval = (0x0) << 12; // Max_Read_Request_Size = 128 B
+ pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL,
+ PCI_EXP_DEVCTL_READRQ, regval);
+
+ // Enable error reporting for: Correctable Errors, Non-Fatal Errors,
+ // Fatal Errors, Unsupported Requests
+ pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, 0,
+ PCI_EXP_DEVCTL_CERE |
+ PCI_EXP_DEVCTL_NFERE |
+ PCI_EXP_DEVCTL_FERE |
+ PCI_EXP_DEVCTL_URRE);
+
+ err = dma_set_mask(PCARD_TO_DEV(pcard), DMA_BIT_MASK(64));
+ if (err) {
+ dev_err(&pcard->pdev->dev,
+ "CANNOT use DMA mask %0llx\n", DMA_BIT_MASK(64));
+ goto out7;
+ }
+ dev_dbg(&pcard->pdev->dev,
+ "Using DMA mask %0llx\n", dma_get_mask(PCARD_TO_DEV(pcard)));
+
+ /*
+ * Step 8: Configure IRQs
+ */
+ err = pci_enable_msi(pcard->pdev);
+ if (err < 0)
+ goto out8a;
+
+ rv = request_irq(pcard->pdev->irq, kp2000_irq_handler, IRQF_SHARED,
+ pcard->name, pcard);
+ if (rv) {
+ dev_err(&pcard->pdev->dev,
+ "kp2000_pcie_probe: failed to request_irq: %d\n", rv);
+ goto out8b;
+ }
+
+ /*
+ * Step 9: Setup sysfs attributes
+ */
+ err = sysfs_create_files(&(pdev->dev.kobj), kp_attr_list);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to add sysfs files: %d\n", err);
+ goto out9;
+ }
+
+ /*
+ * Step 10: Setup misc device
+ */
+ pcard->miscdev.minor = MISC_DYNAMIC_MINOR;
+ pcard->miscdev.fops = &kp2000_fops;
+ pcard->miscdev.parent = &pcard->pdev->dev;
+ pcard->miscdev.name = pcard->name;
+
+ err = misc_register(&pcard->miscdev);
+ if (err) {
+ dev_err(&pcard->pdev->dev,
+ "kp2000_pcie_probe: misc_register failed: %d\n", err);
+ goto out10;
+ }
+
+ /*
+ * Step 11: Probe cores
+ */
+ err = kp2000_probe_cores(pcard);
+ if (err)
+ goto out11;
+
+ /*
+ * Step 12: Enable IRQs in HW
+ */
+ writel(KPC_DMA_CARD_IRQ_ENABLE | KPC_DMA_CARD_USER_INTERRUPT_MODE,
+ pcard->dma_common_regs);
+
+ dev_dbg(&pcard->pdev->dev, "kp2000_pcie_probe() complete!\n");
+ mutex_unlock(&pcard->sem);
+ return 0;
+
+out11:
+ misc_deregister(&pcard->miscdev);
+out10:
+ sysfs_remove_files(&(pdev->dev.kobj), kp_attr_list);
+out9:
+ free_irq(pcard->pdev->irq, pcard);
+out8b:
+ pci_disable_msi(pcard->pdev);
+out8a:
+out7:
+out6:
+ iounmap(pcard->dma_bar_base);
+ pci_release_region(pdev, DMA_BAR);
+ pcard->dma_bar_base = NULL;
+out5:
+ iounmap(pcard->regs_bar_base);
+ pci_release_region(pdev, REG_BAR);
+ pcard->regs_bar_base = NULL;
+out4:
+ pci_disable_device(pcard->pdev);
+out3:
+ mutex_unlock(&pcard->sem);
+ ida_simple_remove(&card_num_ida, pcard->card_num);
+out2:
+ kfree(pcard);
+ return err;
}
-int kp2000_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static void kp2000_pcie_remove(struct pci_dev *pdev)
{
- int err = 0;
- struct kp2000_device *pcard;
- static int card_count = 1;
- int rv;
- unsigned long reg_bar_phys_addr;
- unsigned long reg_bar_phys_len;
- unsigned long dma_bar_phys_addr;
- unsigned long dma_bar_phys_len;
- u16 regval;
-
- dev_dbg(&pdev->dev, "kp2000_pcie_probe(pdev = [%p], id = [%p])\n", pdev, id);
-
- //{ Step 1: Allocate a struct for the pcard
- pcard = kzalloc(sizeof(struct kp2000_device), GFP_KERNEL);
- if (NULL == pcard){
- dev_err(&pdev->dev, "probe: failed to allocate private card data\n");
- return -ENOMEM;
- }
- dev_dbg(&pdev->dev, "probe: allocated struct kp2000_device @ %p\n", pcard);
- //}
-
- //{ Step 2: Initialize trivial pcard elements
- pcard->card_num = card_count;
- card_count++;
- scnprintf(pcard->name, 16, "kpcard%d", pcard->card_num);
-
- mutex_init(&pcard->sem);
- lock_card(pcard);
-
- pcard->pdev = pdev;
- pci_set_drvdata(pdev, pcard);
- //}
-
- //{ Step 3: Enable PCI device
- err = pci_enable_device(pcard->pdev);
- if (err){
- dev_err(&pcard->pdev->dev, "probe: failed to enable PCIE2000 PCIe device (%d)\n", err);
- goto out3;
- }
- //}
-
- //{ Step 4: Setup the Register BAR
- reg_bar_phys_addr = pci_resource_start(pcard->pdev, REG_BAR);
- reg_bar_phys_len = pci_resource_len(pcard->pdev, REG_BAR);
-
- pcard->regs_bar_base = ioremap_nocache(reg_bar_phys_addr, PAGE_SIZE);
- if (NULL == pcard->regs_bar_base){
- dev_err(&pcard->pdev->dev, "probe: REG_BAR could not remap memory to virtual space\n");
- err = -ENODEV;
- goto out4;
- }
- dev_dbg(&pcard->pdev->dev, "probe: REG_BAR virt hardware address start [%p]\n", pcard->regs_bar_base);
-
- err = pci_request_region(pcard->pdev, REG_BAR, KP_DRIVER_NAME_KP2000);
- if (err){
- iounmap(pcard->regs_bar_base);
- dev_err(&pcard->pdev->dev, "probe: failed to acquire PCI region (%d)\n", err);
- err = -ENODEV;
- goto out4;
- }
-
- pcard->regs_base_resource.start = reg_bar_phys_addr;
- pcard->regs_base_resource.end = reg_bar_phys_addr + reg_bar_phys_len - 1;
- pcard->regs_base_resource.flags = IORESOURCE_MEM;
- //}
-
- //{ Step 5: Setup the DMA BAR
- dma_bar_phys_addr = pci_resource_start(pcard->pdev, DMA_BAR);
- dma_bar_phys_len = pci_resource_len(pcard->pdev, DMA_BAR);
-
- pcard->dma_bar_base = ioremap_nocache(dma_bar_phys_addr, dma_bar_phys_len);
- if (NULL == pcard->dma_bar_base){
- dev_err(&pcard->pdev->dev, "probe: DMA_BAR could not remap memory to virtual space\n");
- err = -ENODEV;
- goto out5;
- }
- dev_dbg(&pcard->pdev->dev, "probe: DMA_BAR virt hardware address start [%p]\n", pcard->dma_bar_base);
-
- pcard->dma_common_regs = pcard->dma_bar_base + KPC_DMA_COMMON_OFFSET;
-
- err = pci_request_region(pcard->pdev, DMA_BAR, "kp2000_pcie");
- if (err){
- iounmap(pcard->dma_bar_base);
- dev_err(&pcard->pdev->dev, "probe: failed to acquire PCI region (%d)\n", err);
- err = -ENODEV;
- goto out5;
- }
-
- pcard->dma_base_resource.start = dma_bar_phys_addr;
- pcard->dma_base_resource.end = dma_bar_phys_addr + dma_bar_phys_len - 1;
- pcard->dma_base_resource.flags = IORESOURCE_MEM;
- //}
-
- //{ Step 6: System Regs
- pcard->sysinfo_regs_base = pcard->regs_bar_base;
- err = read_system_regs(pcard);
- if (err)
- goto out6;
-
- // Disable all "user" interrupts because they're not used yet.
- writeq(0xFFFFFFFFFFFFFFFF, pcard->sysinfo_regs_base + REG_INTERRUPT_MASK);
- //}
-
- //{ Step 7: Configure PCI thingies
- // let the card master PCIe
- pci_set_master(pcard->pdev);
- // enable IO and mem if not already done
- pci_read_config_word(pcard->pdev, PCI_COMMAND, ®val);
- regval |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
- pci_write_config_word(pcard->pdev, PCI_COMMAND, regval);
-
- // Clear relaxed ordering bit
- pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN, 0);
-
- // Set Max_Payload_Size and Max_Read_Request_Size
- regval = (0x0) << 5; // Max_Payload_Size = 128 B
- pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_PAYLOAD, regval);
- regval = (0x0) << 12; // Max_Read_Request_Size = 128 B
- pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_READRQ, regval);
-
- // Enable error reporting for: Correctable Errors, Non-Fatal Errors, Fatal Errors, Unsupported Requests
- pcie_capability_clear_and_set_word(pcard->pdev, PCI_EXP_DEVCTL, 0, PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE);
-
- err = dma_set_mask(PCARD_TO_DEV(pcard), DMA_BIT_MASK(64));
- if (err){
- dev_err(&pcard->pdev->dev, "CANNOT use DMA mask %0llx\n", DMA_BIT_MASK(64));
- goto out7;
- }
- dev_dbg(&pcard->pdev->dev, "Using DMA mask %0llx\n", dma_get_mask(PCARD_TO_DEV(pcard)));
- //}
-
- //{ Step 8: Configure IRQs
- err = pci_enable_msi(pcard->pdev);
- if (err < 0)
- goto out8a;
-
- rv = request_irq(pcard->pdev->irq, kp2000_irq_handler, IRQF_SHARED, pcard->name, pcard);
- if (rv){
- dev_err(&pcard->pdev->dev, "kp2000_pcie_probe: failed to request_irq: %d\n", rv);
- goto out8b;
- }
- //}
-
- //{ Step 9: Setup sysfs attributes
- err = sysfs_create_files(&(pdev->dev.kobj), kp_attr_list);
- if (err){
- dev_err(&pdev->dev, "Failed to add sysfs files: %d\n", err);
- goto out9;
- }
- //}
-
- //{ Step 10: Setup misc device
- pcard->miscdev.minor = MISC_DYNAMIC_MINOR;
- pcard->miscdev.fops = &kp2000_fops;
- pcard->miscdev.parent = &pcard->pdev->dev;
- pcard->miscdev.name = pcard->name;
-
- err = misc_register(&pcard->miscdev);
- if (err){
- dev_err(&pcard->pdev->dev, "kp2000_pcie_probe: misc_register failed: %d\n", err);
- goto out10;
- }
- //}
-
- //{ Step 11: Probe cores
- err = kp2000_probe_cores(pcard);
- if (err)
- goto out11;
- //}
-
- //{ Step 12: Enable IRQs in HW
- SetBackEndControl(pcard->dma_common_regs, KPC_DMA_CARD_IRQ_ENABLE | KPC_DMA_CARD_USER_INTERRUPT_MODE);
- //}
-
- dev_dbg(&pcard->pdev->dev, "kp2000_pcie_probe() complete!\n");
- unlock_card(pcard);
- return 0;
-
- out11:
- misc_deregister(&pcard->miscdev);
- out10:
- sysfs_remove_files(&(pdev->dev.kobj), kp_attr_list);
- out9:
- free_irq(pcard->pdev->irq, pcard);
- out8b:
- pci_disable_msi(pcard->pdev);
- out8a:
- out7:
- out6:
- iounmap(pcard->dma_bar_base);
- pci_release_region(pdev, DMA_BAR);
- pcard->dma_bar_base = NULL;
- out5:
- iounmap(pcard->regs_bar_base);
- pci_release_region(pdev, REG_BAR);
- pcard->regs_bar_base = NULL;
- out4:
- pci_disable_device(pcard->pdev);
- out3:
- unlock_card(pcard);
- kfree(pcard);
- return err;
+ struct kp2000_device *pcard = pci_get_drvdata(pdev);
+
+ dev_dbg(&pdev->dev, "kp2000_pcie_remove(pdev=%p)\n", pdev);
+
+ if (pcard == NULL)
+ return;
+
+ mutex_lock(&pcard->sem);
+ kp2000_remove_cores(pcard);
+ mfd_remove_devices(PCARD_TO_DEV(pcard));
+ misc_deregister(&pcard->miscdev);
+ sysfs_remove_files(&(pdev->dev.kobj), kp_attr_list);
+ free_irq(pcard->pdev->irq, pcard);
+ pci_disable_msi(pcard->pdev);
+ if (pcard->dma_bar_base != NULL) {
+ iounmap(pcard->dma_bar_base);
+ pci_release_region(pdev, DMA_BAR);
+ pcard->dma_bar_base = NULL;
+ }
+ if (pcard->regs_bar_base != NULL) {
+ iounmap(pcard->regs_bar_base);
+ pci_release_region(pdev, REG_BAR);
+ pcard->regs_bar_base = NULL;
+ }
+ pci_disable_device(pcard->pdev);
+ pci_set_drvdata(pdev, NULL);
+ mutex_unlock(&pcard->sem);
+ ida_simple_remove(&card_num_ida, pcard->card_num);
+ kfree(pcard);
}
+struct class *kpc_uio_class;
+ATTRIBUTE_GROUPS(kpc_uio_class);
+
+static const struct pci_device_id kp2000_pci_device_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0) },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, kp2000_pci_device_ids);
-void kp2000_pcie_remove(struct pci_dev *pdev)
+static struct pci_driver kp2000_driver_inst = {
+ .name = "kp2000_pcie",
+ .id_table = kp2000_pci_device_ids,
+ .probe = kp2000_pcie_probe,
+ .remove = kp2000_pcie_remove,
+};
+
+static int __init kp2000_pcie_init(void)
{
- struct kp2000_device *pcard = pci_get_drvdata(pdev);
-
- dev_dbg(&pdev->dev, "kp2000_pcie_remove(pdev=%p)\n", pdev);
-
- if (pcard == NULL) return;
-
- lock_card(pcard);
- kp2000_remove_cores(pcard);
- mfd_remove_devices(PCARD_TO_DEV(pcard));
- misc_deregister(&pcard->miscdev);
- sysfs_remove_files(&(pdev->dev.kobj), kp_attr_list);
- free_irq(pcard->pdev->irq, pcard);
- pci_disable_msi(pcard->pdev);
- if (pcard->dma_bar_base != NULL){
- iounmap(pcard->dma_bar_base);
- pci_release_region(pdev, DMA_BAR);
- pcard->dma_bar_base = NULL;
- }
- if (pcard->regs_bar_base != NULL){
- iounmap(pcard->regs_bar_base);
- pci_release_region(pdev, REG_BAR);
- pcard->regs_bar_base = NULL;
- }
- pci_disable_device(pcard->pdev);
- pci_set_drvdata(pdev, NULL);
- unlock_card(pcard);
- kfree(pcard);
+ kpc_uio_class = class_create(THIS_MODULE, "kpc_uio");
+ if (IS_ERR(kpc_uio_class))
+ return PTR_ERR(kpc_uio_class);
+
+ kpc_uio_class->dev_groups = kpc_uio_class_groups;
+ return pci_register_driver(&kp2000_driver_inst);
}
+module_init(kp2000_pcie_init);
+
+static void __exit kp2000_pcie_exit(void)
+{
+ pci_unregister_driver(&kp2000_driver_inst);
+ class_destroy(kpc_uio_class);
+ ida_destroy(&card_num_ida);
+}
+module_exit(kp2000_pcie_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lee.Brooke@Daktronics.com, Matt.Sickler@Daktronics.com");
+MODULE_SOFTDEP("pre: uio post: kpc_nwl_dma kpc_i2c kpc_spi");
#define KPC_DMA_CARD_S2C_INTERRUPT_STATUS_MASK 0x00FF0000
#define KPC_DMA_CARD_C2S_INTERRUPT_STATUS_MASK 0xFF000000
-static inline void SetBackEndControl(void __iomem *regs, u32 value)
-{
- writel(value, regs + 0);
-}
-static inline u32 GetBackEndStatus(void __iomem *regs)
-{
- return readl(regs + 0);
-}
-
-static inline u32 BackEndControlSetClear(void __iomem *regs, u32 set_bits, u32 clear_bits)
-{
- u32 start_val = GetBackEndStatus(regs);
- u32 new_val = start_val;
- new_val &= ~clear_bits;
- new_val |= set_bits;
- SetBackEndControl(regs, new_val);
- return start_val;
-}
-
#endif /* KPC_DMA_COMMON_DEFS_H_ */
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0+
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h> /* printk() */
-#include <linux/slab.h> /* kmalloc() */
-#include <linux/fs.h> /* everything... */
-#include <linux/errno.h> /* error codes */
-#include <linux/types.h> /* size_t */
-#include <linux/cdev.h>
-#include <linux/uaccess.h> /* copy_*_user */
-#include <linux/rwsem.h>
-#include <linux/idr.h>
-#include <linux/io-64-nonatomic-lo-hi.h>
-#include <linux/device.h>
-#include <linux/sched.h>
-#include "pcie.h"
-#include "uapi.h"
-
-int kp2000_cdev_open(struct inode *inode, struct file *filp)
-{
- struct kp2000_device *pcard = container_of(filp->private_data, struct kp2000_device, miscdev);
-
- dev_dbg(&pcard->pdev->dev, "kp2000_cdev_open(filp = [%p], pcard = [%p])\n", filp, pcard);
-
- filp->private_data = pcard; /* so other methods can access it */
-
- return 0;
-}
-
-int kp2000_cdev_close(struct inode *inode, struct file *filp)
-{
- struct kp2000_device *pcard = filp->private_data;
-
- dev_dbg(&pcard->pdev->dev, "kp2000_cdev_close(filp = [%p], pcard = [%p])\n", filp, pcard);
- return 0;
-}
-
-
-ssize_t kp2000_cdev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
-{
- struct kp2000_device *pcard = filp->private_data;
- int cnt = 0;
- int ret;
-#define BUFF_CNT 1024
- char buff[BUFF_CNT] = {0}; //NOTE: Increase this so it is at least as large as all the scnprintfs. And don't use unbounded strings. "%s"
- //NOTE: also, this is a really shitty way to implement the read() call, but it will work for any size 'count'.
-
- if (WARN(NULL == buf, "kp2000_cdev_read: buf is a NULL pointer!\n"))
- return -EINVAL;
-
- cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Card ID : 0x%08x\n", pcard->card_id);
- cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Build Version : 0x%08x\n", pcard->build_version);
- cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Build Date : 0x%08x\n", pcard->build_datestamp);
- cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Build Time : 0x%08x\n", pcard->build_timestamp);
- cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Core Table Offset : 0x%08x\n", pcard->core_table_offset);
- cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Core Table Length : 0x%08x\n", pcard->core_table_length);
- cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "Hardware Revision : 0x%08x\n", pcard->hardware_revision);
- cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "SSID : 0x%016llx\n", pcard->ssid);
- cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "DDNA : 0x%016llx\n", pcard->ddna);
- cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "IRQ Mask : 0x%016llx\n", readq(pcard->sysinfo_regs_base + REG_INTERRUPT_MASK));
- cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "IRQ Active : 0x%016llx\n", readq(pcard->sysinfo_regs_base + REG_INTERRUPT_ACTIVE));
- cnt += scnprintf(buff+cnt, BUFF_CNT-cnt, "CPLD : 0x%016llx\n", readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG));
-
- if (*f_pos >= cnt)
- return 0;
-
- if (count > cnt)
- count = cnt;
-
- ret = copy_to_user(buf, buff + *f_pos, count);
- if (ret)
- return -EFAULT;
- *f_pos += count;
- return count;
-}
-
-ssize_t kp2000_cdev_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
-{
- return -EINVAL;
-}
-
-long kp2000_cdev_ioctl(struct file *filp, unsigned int ioctl_num, unsigned long ioctl_param)
-{
- struct kp2000_device *pcard = filp->private_data;
-
- dev_dbg(&pcard->pdev->dev, "kp2000_cdev_ioctl(filp = [%p], ioctl_num = 0x%08x, ioctl_param = 0x%016lx) pcard = [%p]\n", filp, ioctl_num, ioctl_param, pcard);
-
- switch (ioctl_num){
- case KP2000_IOCTL_GET_CPLD_REG: return readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG);
- case KP2000_IOCTL_GET_PCIE_ERROR_REG: return readq(pcard->sysinfo_regs_base + REG_PCIE_ERROR_COUNT);
-
- case KP2000_IOCTL_GET_EVERYTHING: {
- struct kp2000_regs temp;
- int ret;
-
- memset(&temp, 0, sizeof(temp));
- temp.card_id = pcard->card_id;
- temp.build_version = pcard->build_version;
- temp.build_datestamp = pcard->build_datestamp;
- temp.build_timestamp = pcard->build_timestamp;
- temp.hw_rev = pcard->hardware_revision;
- temp.ssid = pcard->ssid;
- temp.ddna = pcard->ddna;
- temp.cpld_reg = readq(pcard->sysinfo_regs_base + REG_CPLD_CONFIG);
-
- ret = copy_to_user((void*)ioctl_param, (void*)&temp, sizeof(temp));
- if (ret)
- return -EFAULT;
-
- return sizeof(temp);
- }
-
- default:
- return -ENOTTY;
- }
- return -ENOTTY;
-}
-
-
-struct file_operations kp2000_fops = {
- .owner = THIS_MODULE,
- .open = kp2000_cdev_open,
- .release = kp2000_cdev_close,
- .read = kp2000_cdev_read,
- //.write = kp2000_cdev_write,
- //.poll = kp2000_cdev_poll,
- //.fasync = kp2000_cdev_fasync,
- .llseek = noop_llseek,
- .unlocked_ioctl = kp2000_cdev_ioctl,
-};
-
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0+
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/types.h>
-#include <linux/export.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-#include <linux/io.h>
-#include <linux/mfd/core.h>
-#include <linux/platform_device.h>
-#include <linux/ioport.h>
-#include "pcie.h"
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Lee.Brooke@Daktronics.com, Matt.Sickler@Daktronics.com");
-MODULE_SOFTDEP("pre: uio post: kpc_nwl_dma kpc_i2c kpc_spi");
-
-struct class *kpc_uio_class;
-ATTRIBUTE_GROUPS(kpc_uio_class);
-
-static const struct pci_device_id kp2000_pci_device_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS) },
- { PCI_DEVICE(PCI_VENDOR_ID_DAKTRONICS, PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0) },
- { 0, }
-};
-MODULE_DEVICE_TABLE(pci, kp2000_pci_device_ids);
-
-static struct pci_driver kp2000_driver_inst = {
- .name = "kp2000_pcie",
- .id_table = kp2000_pci_device_ids,
- .probe = kp2000_pcie_probe,
- .remove = kp2000_pcie_remove
-};
-
-
-static int __init kp2000_pcie_init(void)
-{
- kpc_uio_class = class_create(THIS_MODULE, "kpc_uio");
- if (IS_ERR(kpc_uio_class))
- return PTR_ERR(kpc_uio_class);
-
- kpc_uio_class->dev_groups = kpc_uio_class_groups;
- return pci_register_driver(&kp2000_driver_inst);
-}
-module_init(kp2000_pcie_init);
-
-static void __exit kp2000_pcie_exit(void)
-{
- pci_unregister_driver(&kp2000_driver_inst);
- class_destroy(kpc_uio_class);
-}
-module_exit(kp2000_pcie_exit);
* 9 <---------------------- IRQ Active Flags ---------------------->
*/
-#define REG_WIDTH 8
-#define REG_MAGIC_NUMBER (0 * REG_WIDTH)
-#define REG_CARD_ID_AND_BUILD (1 * REG_WIDTH)
-#define REG_DATE_AND_TIME_STAMPS (2 * REG_WIDTH)
-#define REG_CORE_TABLE_OFFSET (3 * REG_WIDTH)
-#define REG_FPGA_SSID (4 * REG_WIDTH)
-#define REG_FPGA_HW_ID (5 * REG_WIDTH)
-#define REG_FPGA_DDNA (6 * REG_WIDTH)
-#define REG_CPLD_CONFIG (7 * REG_WIDTH)
-#define REG_INTERRUPT_MASK (8 * REG_WIDTH)
-#define REG_INTERRUPT_ACTIVE (9 * REG_WIDTH)
-#define REG_PCIE_ERROR_COUNT (10 * REG_WIDTH)
-
-#define KP2000_MAGIC_VALUE 0x196C61482231894D
-
-#define PCI_VENDOR_ID_DAKTRONICS 0x1c33
-#define PCI_DEVICE_ID_DAKTRONICS 0x6021
-
-#define DMA_BAR 0
-#define REG_BAR 1
+#define REG_WIDTH 8
+#define REG_MAGIC_NUMBER (0 * REG_WIDTH)
+#define REG_CARD_ID_AND_BUILD (1 * REG_WIDTH)
+#define REG_DATE_AND_TIME_STAMPS (2 * REG_WIDTH)
+#define REG_CORE_TABLE_OFFSET (3 * REG_WIDTH)
+#define REG_FPGA_SSID (4 * REG_WIDTH)
+#define REG_FPGA_HW_ID (5 * REG_WIDTH)
+#define REG_FPGA_DDNA (6 * REG_WIDTH)
+#define REG_CPLD_CONFIG (7 * REG_WIDTH)
+#define REG_INTERRUPT_MASK (8 * REG_WIDTH)
+#define REG_INTERRUPT_ACTIVE (9 * REG_WIDTH)
+#define REG_PCIE_ERROR_COUNT (10 * REG_WIDTH)
+
+#define KP2000_MAGIC_VALUE 0x196C61482231894D
+
+#define PCI_VENDOR_ID_DAKTRONICS 0x1c33
+#define PCI_DEVICE_ID_DAKTRONICS 0x6021
+
+#define DMA_BAR 0
+#define REG_BAR 1
struct kp2000_device {
- struct pci_dev *pdev;
- struct miscdevice miscdev;
- char name[16];
-
- unsigned int card_num;
- struct mutex sem;
-
- void __iomem *sysinfo_regs_base;
- void __iomem *regs_bar_base;
- struct resource regs_base_resource;
- void __iomem *dma_bar_base;
- void __iomem *dma_common_regs;
- struct resource dma_base_resource;
-
- // "System Registers"
- u32 card_id;
- u32 build_version;
- u32 build_datestamp;
- u32 build_timestamp;
- u32 core_table_offset;
- u32 core_table_length;
- u8 core_table_rev;
- u8 hardware_revision;
- u64 ssid;
- u64 ddna;
-
- // IRQ stuff
- unsigned int irq;
-
- struct list_head uio_devices_list;
+ struct pci_dev *pdev;
+ struct miscdevice miscdev;
+ char name[16];
+
+ unsigned int card_num;
+ struct mutex sem;
+
+ void __iomem *sysinfo_regs_base;
+ void __iomem *regs_bar_base;
+ struct resource regs_base_resource;
+ void __iomem *dma_bar_base;
+ void __iomem *dma_common_regs;
+ struct resource dma_base_resource;
+
+ // "System Registers"
+ u32 card_id;
+ u32 build_version;
+ u32 build_datestamp;
+ u32 build_timestamp;
+ u32 core_table_offset;
+ u32 core_table_length;
+ u8 core_table_rev;
+ u8 hardware_revision;
+ u64 ssid;
+ u64 ddna;
+
+ // IRQ stuff
+ unsigned int irq;
+
+ struct list_head uio_devices_list;
};
extern struct class *kpc_uio_class;
extern struct attribute *kpc_uio_class_attrs[];
-int kp2000_pcie_probe(struct pci_dev *dev, const struct pci_device_id *id);
-void kp2000_pcie_remove(struct pci_dev *pdev);
-int kp2000_probe_cores(struct kp2000_device *pcard);
-void kp2000_remove_cores(struct kp2000_device *pcard);
-
-extern struct file_operations kp2000_fops;
-
+int kp2000_probe_cores(struct kp2000_device *pcard);
+void kp2000_remove_cores(struct kp2000_device *pcard);
// Define this quick little macro because the expression is used frequently
-#define PCARD_TO_DEV(pcard) (&(pcard->pdev->dev))
-
-static inline void
-lock_card(struct kp2000_device *pcard)
-{
- BUG_ON(pcard == NULL);
- mutex_lock(&pcard->sem);
-}
-static inline void
-unlock_card(struct kp2000_device *pcard)
-{
- BUG_ON(pcard == NULL);
- mutex_unlock(&pcard->sem);
-}
-
+#define PCARD_TO_DEV(pcard) (&(pcard->pdev->dev))
#endif /* KP2000_PCIE_H */
#include <linux/ioctl.h>
struct kp2000_regs {
- __u32 card_id;
- __u32 build_version;
- __u32 build_datestamp;
- __u32 build_timestamp;
- __u32 hw_rev;
- __u64 ssid;
- __u64 ddna;
- __u64 cpld_reg;
+ __u32 card_id;
+ __u32 build_version;
+ __u32 build_datestamp;
+ __u32 build_timestamp;
+ __u32 hw_rev;
+ __u64 ssid;
+ __u64 ddna;
+ __u64 cpld_reg;
};
-#define KP2000_IOCTL_GET_CPLD_REG _IOR('k', 9, __u32)
-#define KP2000_IOCTL_GET_PCIE_ERROR_REG _IOR('k', 11, __u32)
-#define KP2000_IOCTL_GET_EVERYTHING _IOR('k', 8, struct kp2000_regs*)
+#define KP2000_IOCTL_GET_CPLD_REG _IOR('k', 9, __u32)
+#define KP2000_IOCTL_GET_PCIE_ERROR_REG _IOR('k', 11, __u32)
+#define KP2000_IOCTL_GET_EVERYTHING _IOR('k', 8, struct kp2000_regs*)
#endif /* KP2000_CDEV_UAPI_H_ */
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * KPC2000 i2c driver
+ *
+ * Adapted i2c-i801.c for use with Kadoka hardware.
+ *
+ * Copyright (C) 1998 - 2002
+ * Frodo Looijaard <frodol@dds.nl>,
+ * Philip Edelbrock <phil@netroedge.com>,
+ * Mark D. Studebaker <mdsxyz123@yahoo.com>
+ * Copyright (C) 2007 - 2012
+ * Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2010 Intel Corporation
+ * David Woodhouse <dwmw2@infradead.org>
+ * Copyright (C) 2014-2018 Daktronics
+ * Matt Sickler <matt.sickler@daktronics.com>,
+ * Jordon Hofer <jordon.hofer@daktronics.com>
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include "kpc.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matt.Sickler@Daktronics.com");
+MODULE_SOFTDEP("pre: i2c-dev");
+
+struct i2c_device {
+ unsigned long smba;
+ struct i2c_adapter adapter;
+ unsigned int features;
+};
+
+/*****************************
+ *** Part 1 - i2c Handlers ***
+ *****************************/
+
+#define REG_SIZE 8
+
+/* I801 SMBus address offsets */
+#define SMBHSTSTS(p) ((0 * REG_SIZE) + (p)->smba)
+#define SMBHSTCNT(p) ((2 * REG_SIZE) + (p)->smba)
+#define SMBHSTCMD(p) ((3 * REG_SIZE) + (p)->smba)
+#define SMBHSTADD(p) ((4 * REG_SIZE) + (p)->smba)
+#define SMBHSTDAT0(p) ((5 * REG_SIZE) + (p)->smba)
+#define SMBHSTDAT1(p) ((6 * REG_SIZE) + (p)->smba)
+#define SMBBLKDAT(p) ((7 * REG_SIZE) + (p)->smba)
+#define SMBPEC(p) ((8 * REG_SIZE) + (p)->smba) /* ICH3 and later */
+#define SMBAUXSTS(p) ((12 * REG_SIZE) + (p)->smba) /* ICH4 and later */
+#define SMBAUXCTL(p) ((13 * REG_SIZE) + (p)->smba) /* ICH4 and later */
+
+/* PCI Address Constants */
+#define SMBBAR 4
+#define SMBHSTCFG 0x040
+
+/* Host configuration bits for SMBHSTCFG */
+#define SMBHSTCFG_HST_EN 1
+#define SMBHSTCFG_SMB_SMI_EN 2
+#define SMBHSTCFG_I2C_EN 4
+
+/* Auxiliary control register bits, ICH4+ only */
+#define SMBAUXCTL_CRC 1
+#define SMBAUXCTL_E32B 2
+
+/* kill bit for SMBHSTCNT */
+#define SMBHSTCNT_KILL 2
+
+/* Other settings */
+#define MAX_RETRIES 400
+#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
+
+/* I801 command constants */
+#define I801_QUICK 0x00
+#define I801_BYTE 0x04
+#define I801_BYTE_DATA 0x08
+#define I801_WORD_DATA 0x0C
+#define I801_PROC_CALL 0x10 /* unimplemented */
+#define I801_BLOCK_DATA 0x14
+#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
+#define I801_BLOCK_LAST 0x34
+#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */
+#define I801_START 0x40
+#define I801_PEC_EN 0x80 /* ICH3 and later */
+
+/* I801 Hosts Status register bits */
+#define SMBHSTSTS_BYTE_DONE 0x80
+#define SMBHSTSTS_INUSE_STS 0x40
+#define SMBHSTSTS_SMBALERT_STS 0x20
+#define SMBHSTSTS_FAILED 0x10
+#define SMBHSTSTS_BUS_ERR 0x08
+#define SMBHSTSTS_DEV_ERR 0x04
+#define SMBHSTSTS_INTR 0x02
+#define SMBHSTSTS_HOST_BUSY 0x01
+
+#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | SMBHSTSTS_INTR)
+
+/* Older devices have their ID defined in <linux/pci_ids.h> */
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22
+/* Patsburg also has three 'Integrated Device Function' SMBus controllers */
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22
+#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330
+#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22
+
+#define FEATURE_SMBUS_PEC BIT(0)
+#define FEATURE_BLOCK_BUFFER BIT(1)
+#define FEATURE_BLOCK_PROC BIT(2)
+#define FEATURE_I2C_BLOCK_READ BIT(3)
+/* Not really a feature, but it's convenient to handle it as such */
+#define FEATURE_IDF BIT(15)
+
+// FIXME!
+#undef inb_p
+#define inb_p(a) readq((void*)a)
+#undef outb_p
+#define outb_p(d,a) writeq(d,(void*)a)
+
+/* 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)
+{
+ int status;
+
+ status = inb_p(SMBHSTSTS(priv));
+ if (status & SMBHSTSTS_HOST_BUSY) {
+ dev_err(&priv->adapter.dev, "SMBus is busy, can't use it! (status=%x)\n", status);
+ return -EBUSY;
+ }
+
+ status &= STATUS_FLAGS;
+ if (status) {
+ //dev_dbg(&priv->adapter.dev, "Clearing status flags (%02x)\n", status);
+ outb_p(status, SMBHSTSTS(priv));
+ status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
+ if (status) {
+ dev_err(&priv->adapter.dev, "Failed clearing status flags (%02x)\n", status);
+ return -EBUSY;
+ }
+ }
+ return 0;
+}
+
+/* Convert the status register to an error code, and clear it. */
+static int i801_check_post(struct i2c_device *priv, int status, int timeout)
+{
+ int result = 0;
+
+ /* If the SMBus is still busy, we give up */
+ if (timeout) {
+ dev_err(&priv->adapter.dev, "Transaction timeout\n");
+ /* try to stop the current command */
+ dev_dbg(&priv->adapter.dev, "Terminating the current operation\n");
+ outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL, SMBHSTCNT(priv));
+ usleep_range(1000, 2000);
+ outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL), SMBHSTCNT(priv));
+
+ /* Check if it worked */
+ status = inb_p(SMBHSTSTS(priv));
+ if ((status & SMBHSTSTS_HOST_BUSY) || !(status & SMBHSTSTS_FAILED))
+ dev_err(&priv->adapter.dev, "Failed terminating the transaction\n");
+ outb_p(STATUS_FLAGS, SMBHSTSTS(priv));
+ return -ETIMEDOUT;
+ }
+
+ if (status & SMBHSTSTS_FAILED) {
+ result = -EIO;
+ dev_err(&priv->adapter.dev, "Transaction failed\n");
+ }
+ if (status & SMBHSTSTS_DEV_ERR) {
+ result = -ENXIO;
+ dev_dbg(&priv->adapter.dev, "No response\n");
+ }
+ if (status & SMBHSTSTS_BUS_ERR) {
+ result = -EAGAIN;
+ dev_dbg(&priv->adapter.dev, "Lost arbitration\n");
+ }
+
+ if (result) {
+ /* Clear error flags */
+ outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv));
+ status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
+ if (status)
+ dev_warn(&priv->adapter.dev, "Failed clearing status flags at end of transaction (%02x)\n", status);
+ }
+
+ return result;
+}
+
+static int i801_transaction(struct i2c_device *priv, int xact)
+{
+ int status;
+ int result;
+ int timeout = 0;
+
+ result = i801_check_pre(priv);
+ if (result < 0)
+ return result;
+ /* the current contents of SMBHSTCNT can be overwritten, since PEC,
+ * INTREN, SMBSCMD are passed in xact
+ */
+ outb_p(xact | I801_START, SMBHSTCNT(priv));
+
+ /* We will always wait for a fraction of a second! */
+ do {
+ usleep_range(250, 500);
+ status = inb_p(SMBHSTSTS(priv));
+ } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_RETRIES));
+
+ result = i801_check_post(priv, status, timeout > MAX_RETRIES);
+ if (result < 0)
+ return result;
+
+ outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
+ return 0;
+}
+
+/* wait for INTR bit as advised by Intel */
+static void i801_wait_hwpec(struct i2c_device *priv)
+{
+ int timeout = 0;
+ int status;
+
+ do {
+ usleep_range(250, 500);
+ status = inb_p(SMBHSTSTS(priv));
+ } while ((!(status & SMBHSTSTS_INTR)) && (timeout++ < MAX_RETRIES));
+
+ if (timeout > MAX_RETRIES)
+ dev_dbg(&priv->adapter.dev, "PEC Timeout!\n");
+
+ outb_p(status, SMBHSTSTS(priv));
+}
+
+static int i801_block_transaction_by_block(struct i2c_device *priv, union i2c_smbus_data *data, char read_write, int hwpec)
+{
+ int i, len;
+ int status;
+
+ inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */
+
+ /* Use 32-byte buffer to process this transaction */
+ if (read_write == I2C_SMBUS_WRITE) {
+ len = data->block[0];
+ outb_p(len, SMBHSTDAT0(priv));
+ for (i = 0; i < len; i++)
+ outb_p(data->block[i+1], SMBBLKDAT(priv));
+ }
+
+ status = i801_transaction(priv, I801_BLOCK_DATA | ENABLE_INT9 | I801_PEC_EN * hwpec);
+ if (status)
+ return status;
+
+ if (read_write == I2C_SMBUS_READ) {
+ len = inb_p(SMBHSTDAT0(priv));
+ if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
+ return -EPROTO;
+
+ data->block[0] = len;
+ for (i = 0; i < len; i++)
+ data->block[i + 1] = inb_p(SMBBLKDAT(priv));
+ }
+ return 0;
+}
+
+static int i801_block_transaction_byte_by_byte(struct i2c_device *priv, union i2c_smbus_data *data, char read_write, int command, int hwpec)
+{
+ int i, len;
+ int smbcmd;
+ int status;
+ int result;
+ int timeout;
+
+ result = i801_check_pre(priv);
+ if (result < 0)
+ return result;
+
+ len = data->block[0];
+
+ if (read_write == I2C_SMBUS_WRITE) {
+ outb_p(len, SMBHSTDAT0(priv));
+ outb_p(data->block[1], SMBBLKDAT(priv));
+ }
+
+ for (i = 1; i <= len; i++) {
+ if (i == len && read_write == I2C_SMBUS_READ) {
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA)
+ smbcmd = I801_I2C_BLOCK_LAST;
+ else
+ smbcmd = I801_BLOCK_LAST;
+ } else {
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA && read_write == I2C_SMBUS_READ)
+ smbcmd = I801_I2C_BLOCK_DATA;
+ else
+ smbcmd = I801_BLOCK_DATA;
+ }
+ outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT(priv));
+
+ if (i == 1)
+ outb_p(inb(SMBHSTCNT(priv)) | I801_START, SMBHSTCNT(priv));
+ /* We will always wait for a fraction of a second! */
+ timeout = 0;
+ do {
+ usleep_range(250, 500);
+ status = inb_p(SMBHSTSTS(priv));
+ } while ((!(status & SMBHSTSTS_BYTE_DONE)) && (timeout++ < MAX_RETRIES));
+
+ result = i801_check_post(priv, status, timeout > MAX_RETRIES);
+ if (result < 0)
+ return result;
+ if (i == 1 && read_write == I2C_SMBUS_READ && command != I2C_SMBUS_I2C_BLOCK_DATA) {
+ len = inb_p(SMBHSTDAT0(priv));
+ if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
+ dev_err(&priv->adapter.dev, "Illegal SMBus block read size %d\n", len);
+ /* Recover */
+ while (inb_p(SMBHSTSTS(priv)) & SMBHSTSTS_HOST_BUSY)
+ outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
+ outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
+ return -EPROTO;
+ }
+ data->block[0] = len;
+ }
+
+ /* Retrieve/store value in SMBBLKDAT */
+ if (read_write == I2C_SMBUS_READ)
+ data->block[i] = inb_p(SMBBLKDAT(priv));
+ if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
+ outb_p(data->block[i+1], SMBBLKDAT(priv));
+ /* signals SMBBLKDAT ready */
+ outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS(priv));
+ }
+
+ return 0;
+}
+
+static int i801_set_block_buffer_mode(struct i2c_device *priv)
+{
+ outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv));
+ if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0)
+ return -EIO;
+ return 0;
+}
+
+/* Block transaction function */
+static int i801_block_transaction(struct i2c_device *priv, union i2c_smbus_data *data, char read_write, int command, int hwpec)
+{
+ int result = 0;
+ //unsigned char hostc;
+
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
+ if (read_write == I2C_SMBUS_WRITE) {
+ /* set I2C_EN bit in configuration register */
+ //TODO: Figure out the right thing to do here...
+ //pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
+ //pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc | SMBHSTCFG_I2C_EN);
+ } else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) {
+ dev_err(&priv->adapter.dev, "I2C block read is unsupported!\n");
+ return -EOPNOTSUPP;
+ }
+ }
+
+ if (read_write == I2C_SMBUS_WRITE || command == I2C_SMBUS_I2C_BLOCK_DATA) {
+ if (data->block[0] < 1)
+ data->block[0] = 1;
+ if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
+ data->block[0] = I2C_SMBUS_BLOCK_MAX;
+ } else {
+ data->block[0] = 32; /* max for SMBus block reads */
+ }
+
+ /* Experience has shown that the block buffer can only be used for
+ * SMBus (not I2C) block transactions, even though the datasheet
+ * doesn't mention this limitation.
+ */
+ if ((priv->features & FEATURE_BLOCK_BUFFER) && command != I2C_SMBUS_I2C_BLOCK_DATA && i801_set_block_buffer_mode(priv) == 0)
+ result = i801_block_transaction_by_block(priv, data, read_write, hwpec);
+ else
+ result = i801_block_transaction_byte_by_byte(priv, data, read_write, command, hwpec);
+ if (result == 0 && hwpec)
+ i801_wait_hwpec(priv);
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA && read_write == I2C_SMBUS_WRITE) {
+ /* restore saved configuration register value */
+ //TODO: Figure out the right thing to do here...
+ //pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc);
+ }
+ return result;
+}
+
+/* Return negative errno on error. */
+static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data)
+{
+ int hwpec;
+ int block = 0;
+ int ret, xact = 0;
+ struct i2c_device *priv = i2c_get_adapdata(adap);
+
+ hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA;
+
+ switch (size) {
+ case I2C_SMBUS_QUICK:
+ dev_dbg(&priv->adapter.dev, " [acc] SMBUS_QUICK\n");
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
+ xact = I801_QUICK;
+ break;
+ case I2C_SMBUS_BYTE:
+ dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BYTE\n");
+
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
+ if (read_write == I2C_SMBUS_WRITE)
+ outb_p(command, SMBHSTCMD(priv));
+ xact = I801_BYTE;
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BYTE_DATA\n");
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
+ outb_p(command, SMBHSTCMD(priv));
+ if (read_write == I2C_SMBUS_WRITE)
+ outb_p(data->byte, SMBHSTDAT0(priv));
+ xact = I801_BYTE_DATA;
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ dev_dbg(&priv->adapter.dev, " [acc] SMBUS_WORD_DATA\n");
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
+ outb_p(command, SMBHSTCMD(priv));
+ if (read_write == I2C_SMBUS_WRITE) {
+ outb_p(data->word & 0xff, SMBHSTDAT0(priv));
+ outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv));
+ }
+ xact = I801_WORD_DATA;
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BLOCK_DATA\n");
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
+ outb_p(command, SMBHSTCMD(priv));
+ block = 1;
+ break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ dev_dbg(&priv->adapter.dev, " [acc] SMBUS_I2C_BLOCK_DATA\n");
+ /* NB: page 240 of ICH5 datasheet shows that the R/#W
+ * bit should be cleared here, even when reading
+ */
+ outb_p((addr & 0x7f) << 1, SMBHSTADD(priv));
+ if (read_write == I2C_SMBUS_READ) {
+ /* NB: page 240 of ICH5 datasheet also shows
+ * that DATA1 is the cmd field when reading
+ */
+ outb_p(command, SMBHSTDAT1(priv));
+ } else {
+ outb_p(command, SMBHSTCMD(priv));
+ }
+ block = 1;
+ break;
+ default:
+ dev_dbg(&priv->adapter.dev, " [acc] Unsupported transaction %d\n", size);
+ return -EOPNOTSUPP;
+ }
+
+ if (hwpec) { /* enable/disable hardware PEC */
+ dev_dbg(&priv->adapter.dev, " [acc] hwpec: yes\n");
+ outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv));
+ } else {
+ dev_dbg(&priv->adapter.dev, " [acc] hwpec: no\n");
+ outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC), SMBAUXCTL(priv));
+ }
+
+ if (block) {
+ //ret = 0;
+ dev_dbg(&priv->adapter.dev, " [acc] block: yes\n");
+ ret = i801_block_transaction(priv, data, read_write, size, hwpec);
+ } else {
+ dev_dbg(&priv->adapter.dev, " [acc] block: no\n");
+ ret = i801_transaction(priv, xact | ENABLE_INT9);
+ }
+
+ /* Some BIOSes don't like it when PEC is enabled at reboot or resume
+ * time, so we forcibly disable it after every transaction. Turn off
+ * E32B for the same reason.
+ */
+ if (hwpec || block) {
+ dev_dbg(&priv->adapter.dev, " [acc] hwpec || block\n");
+ outb_p(inb_p(SMBAUXCTL(priv)) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
+ }
+ if (block) {
+ dev_dbg(&priv->adapter.dev, " [acc] block\n");
+ return ret;
+ }
+ if (ret) {
+ dev_dbg(&priv->adapter.dev, " [acc] ret %d\n", ret);
+ return ret;
+ }
+ if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) {
+ dev_dbg(&priv->adapter.dev, " [acc] I2C_SMBUS_WRITE || I801_QUICK -> ret 0\n");
+ return 0;
+ }
+
+ switch (xact & 0x7f) {
+ case I801_BYTE: /* Result put in SMBHSTDAT0 */
+ case I801_BYTE_DATA:
+ dev_dbg(&priv->adapter.dev, " [acc] I801_BYTE or I801_BYTE_DATA\n");
+ data->byte = inb_p(SMBHSTDAT0(priv));
+ break;
+ case I801_WORD_DATA:
+ dev_dbg(&priv->adapter.dev, " [acc] I801_WORD_DATA\n");
+ data->word = inb_p(SMBHSTDAT0(priv)) + (inb_p(SMBHSTDAT1(priv)) << 8);
+ break;
+ }
+ return 0;
+}
+
+static u32 i801_func(struct i2c_adapter *adapter)
+{
+ struct i2c_device *priv = i2c_get_adapdata(adapter);
+
+ /* original settings
+ * u32 f = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ * I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+ * I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
+ * ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
+ * ((priv->features & FEATURE_I2C_BLOCK_READ) ?
+ * I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0);
+ */
+
+ // 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 */
+
+ 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 _BYTE_DATA _WORD_DATA _PROC_CALL _WRITE_BLOCK_DATA _I2C_BLOCK _PEC */
+ return f;
+}
+
+static const struct i2c_algorithm smbus_algorithm = {
+ .smbus_xfer = i801_access,
+ .functionality = i801_func,
+};
+
+/********************************
+ *** Part 2 - Driver Handlers ***
+ ********************************/
+static int pi2c_probe(struct platform_device *pldev)
+{
+ int err;
+ struct i2c_device *priv;
+ struct resource *res;
+
+ priv = devm_kzalloc(&pldev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ i2c_set_adapdata(&priv->adapter, priv);
+ priv->adapter.owner = THIS_MODULE;
+ priv->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ priv->adapter.algo = &smbus_algorithm;
+
+ res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENXIO;
+
+ priv->smba = (unsigned long)devm_ioremap_nocache(&pldev->dev,
+ res->start,
+ resource_size(res));
+ if (!priv->smba)
+ return -ENOMEM;
+
+ platform_set_drvdata(pldev, priv);
+
+ priv->features |= FEATURE_IDF;
+ priv->features |= FEATURE_I2C_BLOCK_READ;
+ priv->features |= FEATURE_SMBUS_PEC;
+ priv->features |= FEATURE_BLOCK_BUFFER;
+
+ //init_MUTEX(&lddata->sem);
+
+ /* set up the sysfs linkage to our parent device */
+ priv->adapter.dev.parent = &pldev->dev;
+
+ /* Retry up to 3 times on lost arbitration */
+ priv->adapter.retries = 3;
+
+ //snprintf(priv->adapter.name, sizeof(priv->adapter.name), "Fake SMBus I801 adapter at %04lx", priv->smba);
+ snprintf(priv->adapter.name, sizeof(priv->adapter.name), "Fake SMBus I801 adapter");
+
+ err = i2c_add_adapter(&priv->adapter);
+ if (err) {
+ dev_err(&priv->adapter.dev, "Failed to add SMBus adapter\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int pi2c_remove(struct platform_device *pldev)
+{
+ struct i2c_device *lddev;
+
+ lddev = (struct i2c_device *)platform_get_drvdata(pldev);
+
+ i2c_del_adapter(&lddev->adapter);
+
+ //TODO: Figure out the right thing to do here...
+ //pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
+ //pci_release_region(dev, SMBBAR);
+ //pci_set_drvdata(dev, NULL);
+
+ //cdev_del(&lddev->cdev);
+
+ return 0;
+}
+
+static struct platform_driver i2c_plat_driver_i = {
+ .probe = pi2c_probe,
+ .remove = pi2c_remove,
+ .driver = {
+ .name = KP_DRIVER_NAME_I2C,
+ },
+};
+
+module_platform_driver(i2c_plat_driver_i);
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * KP2000 SPI controller driver
+ *
+ * Copyright (C) 2014-2018 Daktronics
+ * Author: Matt Sickler <matt.sickler@daktronics.com>
+ * Very loosely based on spi-omap2-mcspi.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/gcd.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/mtd/partitions.h>
+
+#include "kpc.h"
+
+static struct mtd_partition p2kr0_spi0_parts[] = {
+ { .name = "SLOT_0", .size = 7798784, .offset = 0, },
+ { .name = "SLOT_1", .size = 7798784, .offset = MTDPART_OFS_NXTBLK},
+ { .name = "SLOT_2", .size = 7798784, .offset = MTDPART_OFS_NXTBLK},
+ { .name = "SLOT_3", .size = 7798784, .offset = MTDPART_OFS_NXTBLK},
+ { .name = "CS0_EXTRA", .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_NXTBLK},
+};
+static struct mtd_partition p2kr0_spi1_parts[] = {
+ { .name = "SLOT_4", .size = 7798784, .offset = 0, },
+ { .name = "SLOT_5", .size = 7798784, .offset = MTDPART_OFS_NXTBLK},
+ { .name = "SLOT_6", .size = 7798784, .offset = MTDPART_OFS_NXTBLK},
+ { .name = "SLOT_7", .size = 7798784, .offset = MTDPART_OFS_NXTBLK},
+ { .name = "CS1_EXTRA", .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_NXTBLK},
+};
+
+static struct flash_platform_data p2kr0_spi0_pdata = {
+ .name = "SPI0",
+ .nr_parts = ARRAY_SIZE(p2kr0_spi0_parts),
+ .parts = p2kr0_spi0_parts,
+};
+static struct flash_platform_data p2kr0_spi1_pdata = {
+ .name = "SPI1",
+ .nr_parts = ARRAY_SIZE(p2kr0_spi1_parts),
+ .parts = p2kr0_spi1_parts,
+};
+
+static struct spi_board_info p2kr0_board_info[] = {
+ {
+ .modalias = "n25q256a11",
+ .bus_num = 1,
+ .chip_select = 0,
+ .mode = SPI_MODE_0,
+ .platform_data = &p2kr0_spi0_pdata
+ },
+ {
+ .modalias = "n25q256a11",
+ .bus_num = 1,
+ .chip_select = 1,
+ .mode = SPI_MODE_0,
+ .platform_data = &p2kr0_spi1_pdata
+ },
+};
+
+/***************
+ * SPI Defines *
+ ***************/
+#define KP_SPI_REG_CONFIG 0x0 /* 0x00 */
+#define KP_SPI_REG_STATUS 0x1 /* 0x08 */
+#define KP_SPI_REG_FFCTRL 0x2 /* 0x10 */
+#define KP_SPI_REG_TXDATA 0x3 /* 0x18 */
+#define KP_SPI_REG_RXDATA 0x4 /* 0x20 */
+
+#define KP_SPI_CLK 48000000
+#define KP_SPI_MAX_FIFODEPTH 64
+#define KP_SPI_MAX_FIFOWCNT 0xFFFF
+
+#define KP_SPI_REG_CONFIG_TRM_TXRX 0
+#define KP_SPI_REG_CONFIG_TRM_RX 1
+#define KP_SPI_REG_CONFIG_TRM_TX 2
+
+#define KP_SPI_REG_STATUS_RXS 0x01
+#define KP_SPI_REG_STATUS_TXS 0x02
+#define KP_SPI_REG_STATUS_EOT 0x04
+#define KP_SPI_REG_STATUS_TXFFE 0x10
+#define KP_SPI_REG_STATUS_TXFFF 0x20
+#define KP_SPI_REG_STATUS_RXFFE 0x40
+#define KP_SPI_REG_STATUS_RXFFF 0x80
+
+
+
+/******************
+ * SPI Structures *
+ ******************/
+struct kp_spi {
+ struct spi_master *master;
+ u64 __iomem *base;
+ unsigned long phys;
+ struct device *dev;
+ int fifo_depth;
+ unsigned int pin_dir:1;
+};
+
+
+struct kp_spi_controller_state {
+ void __iomem *base;
+ unsigned long phys;
+ unsigned char chip_select;
+ int word_len;
+ s64 conf_cache;
+};
+
+
+union kp_spi_config {
+ /* use this to access individual elements */
+ struct __attribute__((packed)) spi_config_bitfield {
+ unsigned int pha : 1; /* spim_clk Phase */
+ unsigned int pol : 1; /* spim_clk Polarity */
+ unsigned int epol : 1; /* spim_csx Polarity */
+ unsigned int dpe : 1; /* Transmission Enable */
+ unsigned int wl : 5; /* Word Length */
+ unsigned int : 3;
+ unsigned int trm : 2; /* TxRx Mode */
+ unsigned int cs : 4; /* Chip Select */
+ unsigned int wcnt : 7; /* Word Count */
+ unsigned int ffen : 1; /* FIFO Enable */
+ unsigned int spi_en : 1; /* SPI Enable */
+ unsigned int : 5;
+ } bitfield;
+ /* use this to grab the whole register */
+ u32 reg;
+};
+
+
+
+union kp_spi_status {
+ struct __attribute__((packed)) spi_status_bitfield {
+ unsigned int rx : 1; /* Rx Status */
+ unsigned int tx : 1; /* Tx Status */
+ unsigned int eo : 1; /* End of Transfer */
+ unsigned int : 1;
+ unsigned int txffe : 1; /* Tx FIFO Empty */
+ unsigned int txfff : 1; /* Tx FIFO Full */
+ unsigned int rxffe : 1; /* Rx FIFO Empty */
+ unsigned int rxfff : 1; /* Rx FIFO Full */
+ unsigned int : 24;
+ } bitfield;
+ u32 reg;
+};
+
+
+
+union kp_spi_ffctrl {
+ struct __attribute__((packed)) spi_ffctrl_bitfield {
+ unsigned int ffstart : 1; /* FIFO Start */
+ unsigned int : 31;
+ } bitfield;
+ u32 reg;
+};
+
+
+
+/***************
+ * SPI Helpers *
+ ***************/
+ static inline int
+kp_spi_bytes_per_word(int word_len)
+{
+ if (word_len <= 8){
+ return 1;
+ }
+ else if (word_len <= 16) {
+ return 2;
+ }
+ else { /* word_len <= 32 */
+ return 4;
+ }
+}
+
+ static inline u64
+kp_spi_read_reg(struct kp_spi_controller_state *cs, int idx)
+{
+ u64 __iomem *addr = cs->base;
+ u64 val;
+
+ addr += idx;
+ if ((idx == KP_SPI_REG_CONFIG) && (cs->conf_cache >= 0)){
+ return cs->conf_cache;
+ }
+ val = readq((void*)addr);
+ return val;
+}
+
+ static inline void
+kp_spi_write_reg(struct kp_spi_controller_state *cs, int idx, u64 val)
+{
+ u64 __iomem *addr = cs->base;
+ addr += idx;
+ writeq(val, (void*)addr);
+ if (idx == KP_SPI_REG_CONFIG)
+ cs->conf_cache = val;
+}
+
+ static int
+kp_spi_wait_for_reg_bit(struct kp_spi_controller_state *cs, int idx, unsigned long bit)
+{
+ unsigned long timeout;
+ timeout = jiffies + msecs_to_jiffies(1000);
+ while (!(kp_spi_read_reg(cs, idx) & bit)) {
+ if (time_after(jiffies, timeout)) {
+ if (!(kp_spi_read_reg(cs, idx) & bit)) {
+ return -ETIMEDOUT;
+ } else {
+ return 0;
+ }
+ }
+ cpu_relax();
+ }
+ return 0;
+}
+
+ static unsigned
+kp_spi_txrx_pio(struct spi_device *spidev, struct spi_transfer *transfer)
+{
+ struct kp_spi_controller_state *cs = spidev->controller_state;
+ unsigned int count = transfer->len;
+ unsigned int c = count;
+
+ int i;
+ u8 *rx = transfer->rx_buf;
+ const u8 *tx = transfer->tx_buf;
+ int processed = 0;
+
+ if (tx) {
+ for (i = 0 ; i < c ; i++) {
+ char val = *tx++;
+
+ if (kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, KP_SPI_REG_STATUS_TXS) < 0) {
+ goto out;
+ }
+
+ kp_spi_write_reg(cs, KP_SPI_REG_TXDATA, val);
+ processed++;
+ }
+ }
+ else if(rx) {
+ for (i = 0 ; i < c ; i++) {
+ char test=0;
+
+ kp_spi_write_reg(cs, KP_SPI_REG_TXDATA, 0x00);
+
+ if (kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, KP_SPI_REG_STATUS_RXS) < 0) {
+ goto out;
+ }
+
+ test = kp_spi_read_reg(cs, KP_SPI_REG_RXDATA);
+ *rx++ = test;
+ processed++;
+ }
+ }
+
+ if (kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, KP_SPI_REG_STATUS_EOT) < 0) {
+ //TODO: Figure out how to abort transaction?? This has never happened in practice though...
+ }
+
+out:
+ return processed;
+}
+
+/*****************
+ * SPI Functions *
+ *****************/
+ static int
+kp_spi_setup(struct spi_device *spidev)
+{
+ union kp_spi_config sc;
+ struct kp_spi *kpspi = spi_master_get_devdata(spidev->master);
+ struct kp_spi_controller_state *cs;
+
+ /* setup controller state */
+ cs = spidev->controller_state;
+ if (!cs) {
+ cs = kzalloc(sizeof(*cs), GFP_KERNEL);
+ if(!cs) {
+ return -ENOMEM;
+ }
+ cs->base = kpspi->base;
+ cs->phys = kpspi->phys;
+ cs->chip_select = spidev->chip_select;
+ cs->word_len = spidev->bits_per_word;
+ cs->conf_cache = -1;
+ spidev->controller_state = cs;
+ }
+
+ /* set config register */
+ sc.bitfield.wl = spidev->bits_per_word - 1;
+ sc.bitfield.cs = spidev->chip_select;
+ sc.bitfield.spi_en = 0;
+ sc.bitfield.trm = 0;
+ sc.bitfield.ffen = 0;
+ kp_spi_write_reg(spidev->controller_state, KP_SPI_REG_CONFIG, sc.reg);
+ return 0;
+}
+
+ static int
+kp_spi_transfer_one_message(struct spi_master *master, struct spi_message *m)
+{
+ struct kp_spi_controller_state *cs;
+ struct spi_device *spidev;
+ struct kp_spi *kpspi;
+ struct spi_transfer *transfer;
+ union kp_spi_config sc;
+ int status = 0;
+
+ spidev = m->spi;
+ kpspi = spi_master_get_devdata(master);
+ m->actual_length = 0;
+ m->status = 0;
+
+ cs = spidev->controller_state;
+
+ /* reject invalid messages and transfers */
+ if (list_empty(&m->transfers)) {
+ return -EINVAL;
+ }
+
+ /* validate input */
+ list_for_each_entry(transfer, &m->transfers, transfer_list) {
+ const void *tx_buf = transfer->tx_buf;
+ void *rx_buf = transfer->rx_buf;
+ unsigned len = transfer->len;
+
+ if (transfer->speed_hz > KP_SPI_CLK || (len && !(rx_buf || tx_buf))) {
+ dev_dbg(kpspi->dev, " transfer: %d Hz, %d %s%s, %d bpw\n",
+ transfer->speed_hz,
+ len,
+ tx_buf ? "tx" : "",
+ rx_buf ? "rx" : "",
+ transfer->bits_per_word);
+ dev_dbg(kpspi->dev, " transfer -EINVAL\n");
+ return -EINVAL;
+ }
+ if (transfer->speed_hz && (transfer->speed_hz < (KP_SPI_CLK >> 15))) {
+ dev_dbg(kpspi->dev, "speed_hz %d below minimum %d Hz\n",
+ transfer->speed_hz,
+ KP_SPI_CLK >> 15);
+ dev_dbg(kpspi->dev, " speed_hz -EINVAL\n");
+ return -EINVAL;
+ }
+ }
+
+ /* assert chip select to start the sequence*/
+ sc.reg = kp_spi_read_reg(cs, KP_SPI_REG_CONFIG);
+ sc.bitfield.spi_en = 1;
+ kp_spi_write_reg(cs, KP_SPI_REG_CONFIG, sc.reg);
+
+ /* work */
+ if (kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, KP_SPI_REG_STATUS_EOT) < 0) {
+ dev_info(kpspi->dev, "EOT timed out\n");
+ goto out;
+ }
+
+ /* do the transfers for this message */
+ list_for_each_entry(transfer, &m->transfers, transfer_list) {
+ if (transfer->tx_buf == NULL && transfer->rx_buf == NULL && transfer->len) {
+ status = -EINVAL;
+ goto error;
+ }
+
+ /* transfer */
+ if (transfer->len) {
+ unsigned int word_len = spidev->bits_per_word;
+ unsigned count;
+
+ /* set up the transfer... */
+ sc.reg = kp_spi_read_reg(cs, KP_SPI_REG_CONFIG);
+
+ /* ...direction */
+ if (transfer->tx_buf) {
+ sc.bitfield.trm = KP_SPI_REG_CONFIG_TRM_TX;
+ }
+ else if (transfer->rx_buf) {
+ sc.bitfield.trm = KP_SPI_REG_CONFIG_TRM_RX;
+ }
+
+ /* ...word length */
+ if (transfer->bits_per_word) {
+ word_len = transfer->bits_per_word;
+ }
+ cs->word_len = word_len;
+ sc.bitfield.wl = word_len-1;
+
+ /* ...chip select */
+ sc.bitfield.cs = spidev->chip_select;
+
+ /* ...and write the new settings */
+ kp_spi_write_reg(cs, KP_SPI_REG_CONFIG, sc.reg);
+
+ /* do the transfer */
+ count = kp_spi_txrx_pio(spidev, transfer);
+ m->actual_length += count;
+
+ if (count != transfer->len) {
+ status = -EIO;
+ goto error;
+ }
+ }
+
+ if (transfer->delay_usecs) {
+ udelay(transfer->delay_usecs);
+ }
+ }
+
+ /* de-assert chip select to end the sequence */
+ sc.reg = kp_spi_read_reg(cs, KP_SPI_REG_CONFIG);
+ sc.bitfield.spi_en = 0;
+ kp_spi_write_reg(cs, KP_SPI_REG_CONFIG, sc.reg);
+
+out:
+ /* done work */
+ spi_finalize_current_message(master);
+ return 0;
+
+error:
+ m->status = status;
+ return status;
+}
+
+ static void
+kp_spi_cleanup(struct spi_device *spidev)
+{
+ struct kp_spi_controller_state *cs = spidev->controller_state;
+ if (cs) {
+ kfree(cs);
+ }
+}
+
+
+
+/******************
+ * Probe / Remove *
+ ******************/
+ static int
+kp_spi_probe(struct platform_device *pldev)
+{
+ struct kpc_core_device_platdata *drvdata;
+ struct spi_master *master;
+ struct kp_spi *kpspi;
+ struct resource *r;
+ int status = 0;
+ int i;
+
+ drvdata = pldev->dev.platform_data;
+ if (!drvdata){
+ dev_err(&pldev->dev, "kp_spi_probe: platform_data is NULL!\n");
+ return -ENODEV;
+ }
+
+ master = spi_alloc_master(&pldev->dev, sizeof(struct kp_spi));
+ if (master == NULL) {
+ dev_err(&pldev->dev, "kp_spi_probe: master allocation failed\n");
+ return -ENOMEM;
+ }
+
+ /* set up the spi functions */
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+ master->bits_per_word_mask = (unsigned int)SPI_BPW_RANGE_MASK(4, 32);
+ master->setup = kp_spi_setup;
+ master->transfer_one_message = kp_spi_transfer_one_message;
+ master->cleanup = kp_spi_cleanup;
+
+ platform_set_drvdata(pldev, master);
+
+ kpspi = spi_master_get_devdata(master);
+ kpspi->master = master;
+ kpspi->dev = &pldev->dev;
+
+ master->num_chipselect = 4;
+ if (pldev->id != -1) {
+ master->bus_num = pldev->id;
+ }
+ kpspi->pin_dir = 0;
+
+ r = platform_get_resource(pldev, IORESOURCE_MEM, 0);
+ if (r == NULL) {
+ dev_err(&pldev->dev, "kp_spi_probe: Unable to get platform resources\n");
+ status = -ENODEV;
+ goto free_master;
+ }
+
+ kpspi->phys = (unsigned long)ioremap_nocache(r->start, resource_size(r));
+ kpspi->base = (u64 __iomem *)kpspi->phys;
+
+ status = spi_register_master(master);
+ if (status < 0) {
+ dev_err(&pldev->dev, "Unable to register SPI device\n");
+ goto free_master;
+ }
+
+ /* register the slave boards */
+#define NEW_SPI_DEVICE_FROM_BOARD_INFO_TABLE(table) \
+ for (i = 0 ; i < ARRAY_SIZE(table) ; i++) { \
+ spi_new_device(master, &(table[i])); \
+ }
+
+ switch ((drvdata->card_id & 0xFFFF0000) >> 16){
+ case PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0:
+ NEW_SPI_DEVICE_FROM_BOARD_INFO_TABLE(p2kr0_board_info);
+ break;
+ default:
+ dev_err(&pldev->dev, "Unknown hardware, cant know what partition table to use!\n");
+ goto free_master;
+ break;
+ }
+
+ return status;
+
+free_master:
+ spi_master_put(master);
+ return status;
+}
+
+ static int
+kp_spi_remove(struct platform_device *pldev)
+{
+ struct spi_master * master = platform_get_drvdata(pldev);
+ spi_unregister_master(master);
+ return 0;
+}
+
+
+static struct platform_driver kp_spi_driver = {
+ .driver = {
+ .name = KP_DRIVER_NAME_SPI,
+ },
+ .probe = kp_spi_probe,
+ .remove = kp_spi_remove,
+};
+
+module_platform_driver(kp_spi_driver);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:kp_spi");
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
static
irqreturn_t ndd_irq_handler(int irq, void *dev_id)
{
- struct kpc_dma_device *ldev = (struct kpc_dma_device*)dev_id;
-
+ struct kpc_dma_device *ldev = (struct kpc_dma_device *)dev_id;
+
if ((GetEngineControl(ldev) & ENG_CTL_IRQ_ACTIVE) || (ldev->desc_completed->MyDMAAddr != GetEngineCompletePtr(ldev)))
schedule_work(&ldev->irq_work);
-
+
return IRQ_HANDLED;
}
{
struct kpc_dma_descriptor *cur;
struct kpc_dma_device *eng = container_of(ws, struct kpc_dma_device, irq_work);
+
lock_engine(eng);
-
+
if (GetEngineCompletePtr(eng) == 0)
goto out;
-
+
if (eng->desc_completed->MyDMAAddr == GetEngineCompletePtr(eng))
goto out;
-
+
cur = eng->desc_completed;
do {
cur = cur->Next;
dev_dbg(&eng->pldev->dev, "Handling completed descriptor %p (acd = %p)\n", cur, cur->acd);
BUG_ON(cur == eng->desc_next); // Ordering failure.
-
- if (cur->DescControlFlags & DMA_DESC_CTL_SOP){
+
+ if (cur->DescControlFlags & DMA_DESC_CTL_SOP) {
eng->accumulated_bytes = 0;
eng->accumulated_flags = 0;
}
-
+
eng->accumulated_bytes += cur->DescByteCount;
if (cur->DescStatusFlags & DMA_DESC_STS_ERROR)
eng->accumulated_flags |= ACD_FLAG_ENG_ACCUM_ERROR;
-
+
if (cur->DescStatusFlags & DMA_DESC_STS_SHORT)
eng->accumulated_flags |= ACD_FLAG_ENG_ACCUM_SHORT;
-
- if (cur->DescControlFlags & DMA_DESC_CTL_EOP){
+
+ if (cur->DescControlFlags & DMA_DESC_CTL_EOP) {
if (cur->acd)
transfer_complete_cb(cur->acd, eng->accumulated_bytes, eng->accumulated_flags | ACD_FLAG_DONE);
}
-
+
eng->desc_completed = cur;
} while (cur->MyDMAAddr != GetEngineCompletePtr(eng));
-
+
out:
SetClearEngineControl(eng, ENG_CTL_IRQ_ACTIVE, 0);
-
+
unlock_engine(eng);
}
-
/********** DMA Engine Init/Teardown **********/
void start_dma_engine(struct kpc_dma_device *eng)
{
eng->desc_next = eng->desc_pool_first;
eng->desc_completed = eng->desc_pool_last;
-
+
// Setup the engine pointer registers
SetEngineNextPtr(eng, eng->desc_pool_first);
SetEngineSWPtr(eng, eng->desc_pool_first);
ClearEngineCompletePtr(eng);
-
+
WriteEngineControl(eng, ENG_CTL_DMA_ENABLE | ENG_CTL_IRQ_ENABLE);
}
int setup_dma_engine(struct kpc_dma_device *eng, u32 desc_cnt)
{
u32 caps;
- struct kpc_dma_descriptor * cur;
- struct kpc_dma_descriptor * next;
+ struct kpc_dma_descriptor *cur;
+ struct kpc_dma_descriptor *next;
dma_addr_t next_handle;
dma_addr_t head_handle;
unsigned int i;
int rv;
+
dev_dbg(&eng->pldev->dev, "Setting up DMA engine [%p]\n", eng);
-
+
caps = GetEngineCapabilities(eng);
-
- if (WARN(!(caps & ENG_CAP_PRESENT), "setup_dma_engine() called for DMA Engine at %p which isn't present in hardware!\n", eng))
+
+ if (WARN(!(caps & ENG_CAP_PRESENT), "%s() called for DMA Engine at %p which isn't present in hardware!\n", __func__, eng))
return -ENXIO;
-
- if (caps & ENG_CAP_DIRECTION){
+
+ if (caps & ENG_CAP_DIRECTION) {
eng->dir = DMA_FROM_DEVICE;
} else {
eng->dir = DMA_TO_DEVICE;
}
-
+
eng->desc_pool_cnt = desc_cnt;
eng->desc_pool = dma_pool_create("KPC DMA Descriptors", &eng->pldev->dev, sizeof(struct kpc_dma_descriptor), DMA_DESC_ALIGNMENT, 4096);
-
+
eng->desc_pool_first = dma_pool_alloc(eng->desc_pool, GFP_KERNEL | GFP_DMA, &head_handle);
- if (!eng->desc_pool_first){
- dev_err(&eng->pldev->dev, "setup_dma_engine: couldn't allocate desc_pool_first!\n");
+ if (!eng->desc_pool_first) {
+ dev_err(&eng->pldev->dev, "%s: couldn't allocate desc_pool_first!\n", __func__);
dma_pool_destroy(eng->desc_pool);
return -ENOMEM;
}
-
+
eng->desc_pool_first->MyDMAAddr = head_handle;
clear_desc(eng->desc_pool_first);
-
+
cur = eng->desc_pool_first;
- for (i = 1 ; i < eng->desc_pool_cnt ; i++){
+ for (i = 1 ; i < eng->desc_pool_cnt ; i++) {
next = dma_pool_alloc(eng->desc_pool, GFP_KERNEL | GFP_DMA, &next_handle);
if (next == NULL)
goto done_alloc;
-
+
clear_desc(next);
next->MyDMAAddr = next_handle;
-
+
cur->DescNextDescPtr = next_handle;
cur->Next = next;
cur = next;
}
-
+
done_alloc:
// Link the last descriptor back to the first, so it's a circular linked list
cur->Next = eng->desc_pool_first;
cur->DescNextDescPtr = eng->desc_pool_first->MyDMAAddr;
-
+
eng->desc_pool_last = cur;
eng->desc_completed = eng->desc_pool_last;
-
+
// Setup work queue
INIT_WORK(&eng->irq_work, ndd_irq_worker);
-
+
// Grab IRQ line
rv = request_irq(eng->irq, ndd_irq_handler, IRQF_SHARED, KP_DRIVER_NAME_DMA_CONTROLLER, eng);
- if (rv){
- dev_err(&eng->pldev->dev, "setup_dma_engine: failed to request_irq: %d\n", rv);
+ if (rv) {
+ dev_err(&eng->pldev->dev, "%s: failed to request_irq: %d\n", __func__, rv);
return rv;
}
-
+
// Turn on the engine!
start_dma_engine(eng);
unlock_engine(eng);
-
+
return 0;
}
void stop_dma_engine(struct kpc_dma_device *eng)
{
unsigned long timeout;
+
dev_dbg(&eng->pldev->dev, "Destroying DMA engine [%p]\n", eng);
-
+
// Disable the descriptor engine
WriteEngineControl(eng, 0);
-
+
// Wait for descriptor engine to finish current operaion
timeout = jiffies + (HZ / 2);
- while (GetEngineControl(eng) & ENG_CTL_DMA_RUNNING){
- if (time_after(jiffies, timeout)){
+ while (GetEngineControl(eng) & ENG_CTL_DMA_RUNNING) {
+ if (time_after(jiffies, timeout)) {
dev_crit(&eng->pldev->dev, "DMA_RUNNING still asserted!\n");
break;
}
}
-
+
// Request a reset
WriteEngineControl(eng, ENG_CTL_DMA_RESET_REQUEST);
-
+
// Wait for reset request to be processed
timeout = jiffies + (HZ / 2);
- while (GetEngineControl(eng) & (ENG_CTL_DMA_RUNNING | ENG_CTL_DMA_RESET_REQUEST)){
- if (time_after(jiffies, timeout)){
+ while (GetEngineControl(eng) & (ENG_CTL_DMA_RUNNING | ENG_CTL_DMA_RESET_REQUEST)) {
+ if (time_after(jiffies, timeout)) {
dev_crit(&eng->pldev->dev, "ENG_CTL_DMA_RESET_REQUEST still asserted!\n");
break;
}
}
-
+
// Request a reset
WriteEngineControl(eng, ENG_CTL_DMA_RESET);
-
+
// And wait for reset to complete
timeout = jiffies + (HZ / 2);
- while (GetEngineControl(eng) & ENG_CTL_DMA_RESET){
- if (time_after(jiffies, timeout)){
+ while (GetEngineControl(eng) & ENG_CTL_DMA_RESET) {
+ if (time_after(jiffies, timeout)) {
dev_crit(&eng->pldev->dev, "DMA_RESET still asserted!\n");
break;
}
}
-
+
// Clear any persistent bits just to make sure there is no residue from the reset
SetClearEngineControl(eng, (ENG_CTL_IRQ_ACTIVE | ENG_CTL_DESC_COMPLETE | ENG_CTL_DESC_ALIGN_ERR | ENG_CTL_DESC_FETCH_ERR | ENG_CTL_SW_ABORT_ERR | ENG_CTL_DESC_CHAIN_END | ENG_CTL_DMA_WAITING_PERSIST), 0);
-
+
// Reset performance counters
-
+
// Completely disable the engine
WriteEngineControl(eng, 0);
}
void destroy_dma_engine(struct kpc_dma_device *eng)
{
- struct kpc_dma_descriptor * cur;
+ struct kpc_dma_descriptor *cur;
dma_addr_t cur_handle;
unsigned int i;
-
+
stop_dma_engine(eng);
-
+
cur = eng->desc_pool_first;
cur_handle = eng->desc_pool_first->MyDMAAddr;
-
- for (i = 0 ; i < eng->desc_pool_cnt ; i++){
+
+ for (i = 0 ; i < eng->desc_pool_cnt ; i++) {
struct kpc_dma_descriptor *next = cur->Next;
dma_addr_t next_handle = cur->DescNextDescPtr;
+
dma_pool_free(eng->desc_pool, cur, cur_handle);
cur_handle = next_handle;
cur = next;
}
-
+
dma_pool_destroy(eng->desc_pool);
-
+
free_irq(eng->irq, eng);
}
-
-
/********** Helper Functions **********/
int count_descriptors_available(struct kpc_dma_device *eng)
{
u32 count = 0;
struct kpc_dma_descriptor *cur = eng->desc_next;
- while (cur != eng->desc_completed){
+
+ while (cur != eng->desc_completed) {
BUG_ON(cur == NULL);
count++;
cur = cur->Next;
{
unsigned long first = (iov_base & PAGE_MASK) >> PAGE_SHIFT;
unsigned long last = ((iov_base+iov_len-1) & PAGE_MASK) >> PAGE_SHIFT;
+
return last - first + 1;
}
static inline
unsigned int count_parts_for_sge(struct scatterlist *sg)
{
- unsigned int sg_length = sg_dma_len(sg);
- sg_length += (0x80000-1);
- return (sg_length / 0x80000);
+ return DIV_ROUND_UP(sg_dma_len(sg), 0x80000);
}
/********** Transfer Helpers **********/
u64 card_addr;
u64 dma_addr;
u64 user_ctl;
-
+
BUG_ON(priv == NULL);
ldev = priv->ldev;
BUG_ON(ldev == NULL);
-
- dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_transfer(priv = [%p], kcb = [%p], iov_base = [%p], iov_len = %ld) ldev = [%p]\n", priv, kcb, (void*)iov_base, iov_len, ldev);
-
- acd = (struct aio_cb_data *) kzalloc(sizeof(struct aio_cb_data), GFP_KERNEL);
- if (!acd){
+
+ dev_dbg(&priv->ldev->pldev->dev, "%s(priv = [%p], kcb = [%p], iov_base = [%p], iov_len = %ld) ldev = [%p]\n", __func__, priv, kcb, (void *)iov_base, iov_len, ldev);
+
+ acd = kzalloc(sizeof(*acd), GFP_KERNEL);
+ if (!acd) {
dev_err(&priv->ldev->pldev->dev, "Couldn't kmalloc space for for the aio data\n");
return -ENOMEM;
}
memset(acd, 0x66, sizeof(struct aio_cb_data));
-
+
acd->priv = priv;
acd->ldev = priv->ldev;
acd->cpl = &done;
acd->kcb = kcb;
acd->len = iov_len;
acd->page_count = count_pages(iov_base, iov_len);
-
+
// Allocate an array of page pointers
acd->user_pages = kzalloc(sizeof(struct page *) * acd->page_count, GFP_KERNEL);
- if (!acd->user_pages){
+ if (!acd->user_pages) {
dev_err(&priv->ldev->pldev->dev, "Couldn't kmalloc space for for the page pointers\n");
rv = -ENOMEM;
goto err_alloc_userpages;
}
-
+
// Lock the user buffer pages in memory, and hold on to the page pointers (for the sglist)
down_read(¤t->mm->mmap_sem); /* get memory map semaphore */
rv = get_user_pages(iov_base, acd->page_count, FOLL_TOUCH | FOLL_WRITE | FOLL_GET, acd->user_pages, NULL);
up_read(¤t->mm->mmap_sem); /* release the semaphore */
- if (rv != acd->page_count){
+ if (rv != acd->page_count) {
dev_err(&priv->ldev->pldev->dev, "Couldn't get_user_pages (%ld)\n", rv);
goto err_get_user_pages;
}
-
+
// Allocate and setup the sg_table (scatterlist entries)
rv = sg_alloc_table_from_pages(&acd->sgt, acd->user_pages, acd->page_count, iov_base & (PAGE_SIZE-1), iov_len, GFP_KERNEL);
- if (rv){
+ if (rv) {
dev_err(&priv->ldev->pldev->dev, "Couldn't alloc sg_table (%ld)\n", rv);
goto err_alloc_sg_table;
}
-
+
// Setup the DMA mapping for all the sg entries
acd->mapped_entry_count = dma_map_sg(&ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, ldev->dir);
- if (acd->mapped_entry_count <= 0){
+ if (acd->mapped_entry_count <= 0) {
dev_err(&priv->ldev->pldev->dev, "Couldn't dma_map_sg (%d)\n", acd->mapped_entry_count);
goto err_dma_map_sg;
}
// Calculate how many descriptors are actually needed for this transfer.
- for_each_sg(acd->sgt.sgl, sg, acd->mapped_entry_count, i){
+ for_each_sg(acd->sgt.sgl, sg, acd->mapped_entry_count, i) {
desc_needed += count_parts_for_sge(sg);
}
-
+
lock_engine(ldev);
-
+
// Figoure out how many descriptors are available and return an error if there aren't enough
num_descrs_avail = count_descriptors_available(ldev);
dev_dbg(&priv->ldev->pldev->dev, " mapped_entry_count = %d num_descrs_needed = %d num_descrs_avail = %d\n", acd->mapped_entry_count, desc_needed, num_descrs_avail);
- if (desc_needed >= ldev->desc_pool_cnt){
+ if (desc_needed >= ldev->desc_pool_cnt) {
dev_warn(&priv->ldev->pldev->dev, " mapped_entry_count = %d num_descrs_needed = %d num_descrs_avail = %d TOO MANY to ever complete!\n", acd->mapped_entry_count, desc_needed, num_descrs_avail);
rv = -EAGAIN;
goto err_descr_too_many;
}
- if (desc_needed > num_descrs_avail){
+ if (desc_needed > num_descrs_avail) {
dev_warn(&priv->ldev->pldev->dev, " mapped_entry_count = %d num_descrs_needed = %d num_descrs_avail = %d Too many to complete right now.\n", acd->mapped_entry_count, desc_needed, num_descrs_avail);
rv = -EMSGSIZE;
goto err_descr_too_many;
// Loop through all the sg table entries and fill out a descriptor for each one.
desc = ldev->desc_next;
card_addr = acd->priv->card_addr;
- for_each_sg(acd->sgt.sgl, sg, acd->mapped_entry_count, i){
+ for_each_sg(acd->sgt.sgl, sg, acd->mapped_entry_count, i) {
pcnt = count_parts_for_sge(sg);
- for (p = 0 ; p < pcnt ; p++){
+ for (p = 0 ; p < pcnt ; p++) {
// Fill out the descriptor
BUG_ON(desc == NULL);
clear_desc(desc);
- if (p != pcnt-1){
+ if (p != pcnt-1) {
desc->DescByteCount = 0x80000;
} else {
desc->DescByteCount = sg_dma_len(sg) - (p * 0x80000);
}
desc->DescBufferByteCount = desc->DescByteCount;
-
+
desc->DescControlFlags |= DMA_DESC_CTL_IRQONERR;
if (i == 0 && p == 0)
desc->DescControlFlags |= DMA_DESC_CTL_SOP;
if (i == acd->mapped_entry_count-1 && p == pcnt-1)
desc->DescControlFlags |= DMA_DESC_CTL_EOP | DMA_DESC_CTL_IRQONDONE;
-
+
desc->DescCardAddrLS = (card_addr & 0xFFFFFFFF);
desc->DescCardAddrMS = (card_addr >> 32) & 0xF;
card_addr += desc->DescByteCount;
-
+
dma_addr = sg_dma_address(sg) + (p * 0x80000);
desc->DescSystemAddrLS = (dma_addr & 0x00000000FFFFFFFF) >> 0;
desc->DescSystemAddrMS = (dma_addr & 0xFFFFFFFF00000000) >> 32;
-
+
user_ctl = acd->priv->user_ctl;
- if (i == acd->mapped_entry_count-1 && p == pcnt-1){
+ if (i == acd->mapped_entry_count-1 && p == pcnt-1) {
user_ctl = acd->priv->user_ctl_last;
}
desc->DescUserControlLS = (user_ctl & 0x00000000FFFFFFFF) >> 0;
desc->DescUserControlMS = (user_ctl & 0xFFFFFFFF00000000) >> 32;
-
+
if (i == acd->mapped_entry_count-1 && p == pcnt-1)
desc->acd = acd;
-
+
dev_dbg(&priv->ldev->pldev->dev, " Filled descriptor %p (acd = %p)\n", desc, desc->acd);
-
+
ldev->desc_next = desc->Next;
desc = desc->Next;
}
}
-
+
// Send the filled descriptors off to the hardware to process!
SetEngineSWPtr(ldev, ldev->desc_next);
-
+
unlock_engine(ldev);
-
+
// If this is a synchronous kiocb, we need to put the calling process to sleep until the transfer is complete
- if (kcb == NULL || is_sync_kiocb(kcb)){
+ if (kcb == NULL || is_sync_kiocb(kcb)) {
rv = wait_for_completion_interruptible(&done);
// If the user aborted (rv == -ERESTARTSYS), we're no longer responsible for cleaning up the acd
- if (rv == -ERESTARTSYS){
+ if (rv == -ERESTARTSYS) {
acd->cpl = NULL;
}
- if (rv == 0){
+ if (rv == 0) {
rv = acd->len;
kfree(acd);
}
return rv;
}
-
+
return -EIOCBQUEUED;
err_descr_too_many:
sg_free_table(&acd->sgt);
err_dma_map_sg:
err_alloc_sg_table:
- for (i = 0 ; i < acd->page_count ; i++){
+ for (i = 0 ; i < acd->page_count ; i++) {
put_page(acd->user_pages[i]);
}
err_get_user_pages:
kfree(acd->user_pages);
err_alloc_userpages:
kfree(acd);
- dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_transfer returning with error %ld\n", rv);
+ dev_dbg(&priv->ldev->pldev->dev, "%s returning with error %ld\n", __func__, rv);
return rv;
}
void transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags)
{
unsigned int i;
-
+
BUG_ON(acd == NULL);
BUG_ON(acd->user_pages == NULL);
BUG_ON(acd->sgt.sgl == NULL);
BUG_ON(acd->ldev == NULL);
BUG_ON(acd->ldev->pldev == NULL);
-
- dev_dbg(&acd->ldev->pldev->dev, "transfer_complete_cb(acd = [%p])\n", acd);
-
- for (i = 0 ; i < acd->page_count ; i++){
- if (!PageReserved(acd->user_pages[i])){
+
+ dev_dbg(&acd->ldev->pldev->dev, "%s(acd = [%p])\n", __func__, acd);
+
+ for (i = 0 ; i < acd->page_count ; i++) {
+ if (!PageReserved(acd->user_pages[i])) {
set_page_dirty(acd->user_pages[i]);
}
}
-
+
dma_unmap_sg(&acd->ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, acd->ldev->dir);
-
- for (i = 0 ; i < acd->page_count ; i++){
+
+ for (i = 0 ; i < acd->page_count ; i++) {
put_page(acd->user_pages[i]);
}
-
+
sg_free_table(&acd->sgt);
-
+
kfree(acd->user_pages);
-
+
acd->flags = flags;
-
- if (acd->kcb == NULL || is_sync_kiocb(acd->kcb)){
- if (acd->cpl){
+
+ if (acd->kcb == NULL || is_sync_kiocb(acd->kcb)) {
+ if (acd->cpl) {
complete(acd->cpl);
} else {
// There's no completion, so we're responsible for cleaning up the acd
{
struct dev_private_data *priv;
struct kpc_dma_device *ldev = kpc_dma_lookup_device(iminor(inode));
+
if (ldev == NULL)
return -ENODEV;
-
- if (! atomic_dec_and_test(&ldev->open_count)){
+
+ if (!atomic_dec_and_test(&ldev->open_count)) {
atomic_inc(&ldev->open_count);
return -EBUSY; /* already open */
}
-
+
priv = kzalloc(sizeof(struct dev_private_data), GFP_KERNEL);
if (!priv)
return -ENOMEM;
-
+
priv->ldev = ldev;
filp->private_data = priv;
-
- dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_open(inode = [%p], filp = [%p]) priv = [%p] ldev = [%p]\n", inode, filp, priv, priv->ldev);
+
+ dev_dbg(&priv->ldev->pldev->dev, "%s(inode = [%p], filp = [%p]) priv = [%p] ldev = [%p]\n", __func__, inode, filp, priv, priv->ldev);
return 0;
}
struct kpc_dma_descriptor *cur;
struct dev_private_data *priv = (struct dev_private_data *)filp->private_data;
struct kpc_dma_device *eng = priv->ldev;
- dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_close(inode = [%p], filp = [%p]) priv = [%p], ldev = [%p]\n", inode, filp, priv, priv->ldev);
-
+
+ dev_dbg(&priv->ldev->pldev->dev, "%s(inode = [%p], filp = [%p]) priv = [%p], ldev = [%p]\n", __func__, inode, filp, priv, priv->ldev);
+
lock_engine(eng);
-
+
stop_dma_engine(eng);
-
+
cur = eng->desc_completed->Next;
- while (cur != eng->desc_next){
+ while (cur != eng->desc_next) {
dev_dbg(&eng->pldev->dev, "Aborting descriptor %p (acd = %p)\n", cur, cur->acd);
- if (cur->DescControlFlags & DMA_DESC_CTL_EOP){
+ if (cur->DescControlFlags & DMA_DESC_CTL_EOP) {
if (cur->acd)
transfer_complete_cb(cur->acd, 0, ACD_FLAG_ABORT);
}
-
+
clear_desc(cur);
eng->desc_completed = cur;
-
+
cur = cur->Next;
}
-
+
start_dma_engine(eng);
-
+
unlock_engine(eng);
-
+
atomic_inc(&priv->ldev->open_count); /* release the device */
kfree(priv);
return 0;
int kpc_dma_aio_cancel(struct kiocb *kcb)
{
struct dev_private_data *priv = (struct dev_private_data *)kcb->ki_filp->private_data;
- dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_aio_cancel(kcb = [%p]) priv = [%p], ldev = [%p]\n", kcb, priv, priv->ldev);
+
+ dev_dbg(&priv->ldev->pldev->dev, "%s(kcb = [%p]) priv = [%p], ldev = [%p]\n", __func__, kcb, priv, priv->ldev);
return 0;
}
ssize_t kpc_dma_aio_read(struct kiocb *kcb, const struct iovec *iov, unsigned long iov_count, loff_t pos)
{
struct dev_private_data *priv = (struct dev_private_data *)kcb->ki_filp->private_data;
- dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_aio_read(kcb = [%p], iov = [%p], iov_count = %ld, pos = %lld) priv = [%p], ldev = [%p]\n", kcb, iov, iov_count, pos, priv, priv->ldev);
-
+
+ dev_dbg(&priv->ldev->pldev->dev, "%s(kcb = [%p], iov = [%p], iov_count = %ld, pos = %lld) priv = [%p], ldev = [%p]\n", __func__, kcb, iov, iov_count, pos, priv, priv->ldev);
+
if (priv->ldev->dir != DMA_FROM_DEVICE)
return -EMEDIUMTYPE;
-
- if (iov_count != 1){
- dev_err(&priv->ldev->pldev->dev, "kpc_dma_aio_read() called with iov_count > 1!\n");
+
+ if (iov_count != 1) {
+ dev_err(&priv->ldev->pldev->dev, "%s() called with iov_count > 1!\n", __func__);
return -EFAULT;
}
-
+
if (!is_sync_kiocb(kcb))
kiocb_set_cancel_fn(kcb, kpc_dma_aio_cancel);
return kpc_dma_transfer(priv, kcb, (unsigned long)iov->iov_base, iov->iov_len);
ssize_t kpc_dma_aio_write(struct kiocb *kcb, const struct iovec *iov, unsigned long iov_count, loff_t pos)
{
struct dev_private_data *priv = (struct dev_private_data *)kcb->ki_filp->private_data;
- dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_aio_write(kcb = [%p], iov = [%p], iov_count = %ld, pos = %lld) priv = [%p], ldev = [%p]\n", kcb, iov, iov_count, pos, priv, priv->ldev);
-
+
+ dev_dbg(&priv->ldev->pldev->dev, "%s(kcb = [%p], iov = [%p], iov_count = %ld, pos = %lld) priv = [%p], ldev = [%p]\n", __func__, kcb, iov, iov_count, pos, priv, priv->ldev);
+
if (priv->ldev->dir != DMA_TO_DEVICE)
return -EMEDIUMTYPE;
-
- if (iov_count != 1){
- dev_err(&priv->ldev->pldev->dev, "kpc_dma_aio_write() called with iov_count > 1!\n");
+
+ if (iov_count != 1) {
+ dev_err(&priv->ldev->pldev->dev, "%s() called with iov_count > 1!\n", __func__);
return -EFAULT;
}
-
+
if (!is_sync_kiocb(kcb))
kiocb_set_cancel_fn(kcb, kpc_dma_aio_cancel);
return kpc_dma_transfer(priv, kcb, (unsigned long)iov->iov_base, iov->iov_len);
#endif
static
-ssize_t kpc_dma_read( struct file *filp, char __user *user_buf, size_t count, loff_t *ppos)
+ssize_t kpc_dma_read(struct file *filp, char __user *user_buf, size_t count, loff_t *ppos)
{
struct dev_private_data *priv = (struct dev_private_data *)filp->private_data;
- dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_read(filp = [%p], user_buf = [%p], count = %zu, ppos = [%p]) priv = [%p], ldev = [%p]\n", filp, user_buf, count, ppos, priv, priv->ldev);
-
+
+ dev_dbg(&priv->ldev->pldev->dev, "%s(filp = [%p], user_buf = [%p], count = %zu, ppos = [%p]) priv = [%p], ldev = [%p]\n", __func__, filp, user_buf, count, ppos, priv, priv->ldev);
+
if (priv->ldev->dir != DMA_FROM_DEVICE)
return -EMEDIUMTYPE;
-
+
return kpc_dma_transfer(priv, (struct kiocb *)NULL, (unsigned long)user_buf, count);
}
ssize_t kpc_dma_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *ppos)
{
struct dev_private_data *priv = (struct dev_private_data *)filp->private_data;
- dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_write(filp = [%p], user_buf = [%p], count = %zu, ppos = [%p]) priv = [%p], ldev = [%p]\n", filp, user_buf, count, ppos, priv, priv->ldev);
-
+
+ dev_dbg(&priv->ldev->pldev->dev, "%s(filp = [%p], user_buf = [%p], count = %zu, ppos = [%p]) priv = [%p], ldev = [%p]\n", __func__, filp, user_buf, count, ppos, priv, priv->ldev);
+
if (priv->ldev->dir != DMA_TO_DEVICE)
return -EMEDIUMTYPE;
-
+
return kpc_dma_transfer(priv, (struct kiocb *)NULL, (unsigned long)user_buf, count);
}
long kpc_dma_ioctl(struct file *filp, unsigned int ioctl_num, unsigned long ioctl_param)
{
struct dev_private_data *priv = (struct dev_private_data *)filp->private_data;
- dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_ioctl(filp = [%p], ioctl_num = 0x%x, ioctl_param = 0x%lx) priv = [%p], ldev = [%p]\n", filp, ioctl_num, ioctl_param, priv, priv->ldev);
-
- switch (ioctl_num){
- case KND_IOCTL_SET_CARD_ADDR: priv->card_addr = ioctl_param; return priv->card_addr;
- case KND_IOCTL_SET_USER_CTL: priv->user_ctl = ioctl_param; return priv->user_ctl;
- case KND_IOCTL_SET_USER_CTL_LAST: priv->user_ctl_last = ioctl_param; return priv->user_ctl_last;
- case KND_IOCTL_GET_USER_STS: return priv->user_sts;
+
+ dev_dbg(&priv->ldev->pldev->dev, "%s(filp = [%p], ioctl_num = 0x%x, ioctl_param = 0x%lx) priv = [%p], ldev = [%p]\n", __func__, filp, ioctl_num, ioctl_param, priv, priv->ldev);
+
+ switch (ioctl_num) {
+ case KND_IOCTL_SET_CARD_ADDR:
+ priv->card_addr = ioctl_param; return priv->card_addr;
+ case KND_IOCTL_SET_USER_CTL:
+ priv->user_ctl = ioctl_param; return priv->user_ctl;
+ case KND_IOCTL_SET_USER_CTL_LAST:
+ priv->user_ctl_last = ioctl_param; return priv->user_ctl_last;
+ case KND_IOCTL_GET_USER_STS:
+ return priv->user_sts;
}
-
+
return -ENOTTY;
}
-
-struct file_operations kpc_dma_fops = {
+const struct file_operations kpc_dma_fops = {
.owner = THIS_MODULE,
.open = kpc_dma_open,
.release = kpc_dma_close,
MODULE_AUTHOR("Matt.Sickler@daktronics.com");
#define KPC_DMA_CHAR_MAJOR UNNAMED_MAJOR
-#define KPC_DMA_NUM_MINORS 1 << MINORBITS
+#define KPC_DMA_NUM_MINORS BIT(MINORBITS)
static DEFINE_MUTEX(kpc_dma_mtx);
static int assigned_major_num;
static LIST_HEAD(kpc_dma_list);
-
/********** kpc_dma_list list management **********/
-struct kpc_dma_device * kpc_dma_lookup_device(int minor)
+struct kpc_dma_device *kpc_dma_lookup_device(int minor)
{
struct kpc_dma_device *c;
+
mutex_lock(&kpc_dma_mtx);
list_for_each_entry(c, &kpc_dma_list, list) {
if (c->pldev->id == minor) {
}
}
c = NULL; // not-found case
- out:
+out:
mutex_unlock(&kpc_dma_mtx);
return c;
}
-void kpc_dma_add_device(struct kpc_dma_device * ldev)
+void kpc_dma_add_device(struct kpc_dma_device *ldev)
{
mutex_lock(&kpc_dma_mtx);
list_add(&ldev->list, &kpc_dma_list);
mutex_unlock(&kpc_dma_mtx);
}
-void kpc_dma_del_device(struct kpc_dma_device * ldev)
+void kpc_dma_del_device(struct kpc_dma_device *ldev)
{
mutex_lock(&kpc_dma_mtx);
list_del(&ldev->list);
{
struct kpc_dma_device *ldev;
struct platform_device *pldev = to_platform_device(dev);
- if (!pldev) return 0;
+
+ if (!pldev)
+ return 0;
ldev = platform_get_drvdata(pldev);
- if (!ldev) return 0;
-
- return scnprintf(buf, PAGE_SIZE,
+ if (!ldev)
+ return 0;
+
+ return scnprintf(buf, PAGE_SIZE,
"EngineControlStatus = 0x%08x\n"
"RegNextDescPtr = 0x%08x\n"
"RegSWDescPtr = 0x%08x\n"
}
DEVICE_ATTR(engine_regs, 0444, show_engine_regs, NULL);
-static const struct attribute * ndd_attr_list[] = {
+static const struct attribute *ndd_attr_list[] = {
&dev_attr_engine_regs.attr,
NULL,
};
struct class *kpc_dma_class;
-
/********** Platform Driver Functions **********/
static
int kpc_dma_probe(struct platform_device *pldev)
struct resource *r = NULL;
int rv = 0;
dev_t dev;
-
+
struct kpc_dma_device *ldev = kzalloc(sizeof(struct kpc_dma_device), GFP_KERNEL);
- if (!ldev){
- dev_err(&pldev->dev, "kpc_dma_probe: unable to kzalloc space for kpc_dma_device\n");
+
+ if (!ldev) {
+ dev_err(&pldev->dev, "%s: unable to kzalloc space for kpc_dma_device\n", __func__);
rv = -ENOMEM;
goto err_rv;
}
-
- dev_dbg(&pldev->dev, "kpc_dma_probe(pldev = [%p]) ldev = [%p]\n", pldev, ldev);
-
+
+ dev_dbg(&pldev->dev, "%s(pldev = [%p]) ldev = [%p]\n", __func__, pldev, ldev);
+
INIT_LIST_HEAD(&ldev->list);
-
+
ldev->pldev = pldev;
platform_set_drvdata(pldev, ldev);
atomic_set(&ldev->open_count, 1);
-
+
mutex_init(&ldev->sem);
lock_engine(ldev);
-
+
// Get Engine regs resource
r = platform_get_resource(pldev, IORESOURCE_MEM, 0);
- if (!r){
- dev_err(&ldev->pldev->dev, "kpc_dma_probe: didn't get the engine regs resource!\n");
+ if (!r) {
+ dev_err(&ldev->pldev->dev, "%s: didn't get the engine regs resource!\n", __func__);
rv = -ENXIO;
goto err_kfree;
}
ldev->eng_regs = ioremap_nocache(r->start, resource_size(r));
- if (!ldev->eng_regs){
- dev_err(&ldev->pldev->dev, "kpc_dma_probe: failed to ioremap engine regs!\n");
+ if (!ldev->eng_regs) {
+ dev_err(&ldev->pldev->dev, "%s: failed to ioremap engine regs!\n", __func__);
rv = -ENXIO;
goto err_kfree;
}
-
+
r = platform_get_resource(pldev, IORESOURCE_IRQ, 0);
- if (!r){
- dev_err(&ldev->pldev->dev, "kpc_dma_probe: didn't get the IRQ resource!\n");
+ if (!r) {
+ dev_err(&ldev->pldev->dev, "%s: didn't get the IRQ resource!\n", __func__);
rv = -ENXIO;
goto err_kfree;
}
ldev->irq = r->start;
-
+
// Setup miscdev struct
dev = MKDEV(assigned_major_num, pldev->id);
ldev->kpc_dma_dev = device_create(kpc_dma_class, &pldev->dev, dev, ldev, "kpc_dma%d", pldev->id);
- if (IS_ERR(ldev->kpc_dma_dev)){
- dev_err(&ldev->pldev->dev, "kpc_dma_probe: device_create failed: %d\n", rv);
+ if (IS_ERR(ldev->kpc_dma_dev)) {
+ dev_err(&ldev->pldev->dev, "%s: device_create failed: %d\n", __func__, rv);
goto err_kfree;
}
-
+
// Setup the DMA engine
rv = setup_dma_engine(ldev, 30);
- if (rv){
- dev_err(&ldev->pldev->dev, "kpc_dma_probe: failed to setup_dma_engine: %d\n", rv);
+ if (rv) {
+ dev_err(&ldev->pldev->dev, "%s: failed to setup_dma_engine: %d\n", __func__, rv);
goto err_misc_dereg;
}
-
+
// Setup the sysfs files
rv = sysfs_create_files(&(ldev->pldev->dev.kobj), ndd_attr_list);
- if (rv){
- dev_err(&ldev->pldev->dev, "kpc_dma_probe: Failed to add sysfs files: %d\n", rv);
+ if (rv) {
+ dev_err(&ldev->pldev->dev, "%s: Failed to add sysfs files: %d\n", __func__, rv);
goto err_destroy_eng;
}
-
+
kpc_dma_add_device(ldev);
-
+
return 0;
-
+
err_destroy_eng:
destroy_dma_engine(ldev);
err_misc_dereg:
int kpc_dma_remove(struct platform_device *pldev)
{
struct kpc_dma_device *ldev = platform_get_drvdata(pldev);
+
if (!ldev)
return -ENXIO;
-
- dev_dbg(&ldev->pldev->dev, "kpc_dma_remove(pldev = [%p]) ldev = [%p]\n", pldev, ldev);
-
+
+ dev_dbg(&ldev->pldev->dev, "%s(pldev = [%p]) ldev = [%p]\n", __func__, pldev, ldev);
+
lock_engine(ldev);
sysfs_remove_files(&(ldev->pldev->dev.kobj), ndd_attr_list);
destroy_dma_engine(ldev);
kpc_dma_del_device(ldev);
device_destroy(kpc_dma_class, MKDEV(assigned_major_num, ldev->pldev->id));
kfree(ldev);
-
+
return 0;
}
-
/********** Driver Functions **********/
struct platform_driver kpc_dma_plat_driver_i = {
.probe = kpc_dma_probe,
};
static
-int __init kpc_dma_driver_init(void)
+int __init kpc_dma_driver_init(void)
{
int err;
-
+
err = __register_chrdev(KPC_DMA_CHAR_MAJOR, 0, KPC_DMA_NUM_MINORS, "kpc_dma", &kpc_dma_fops);
- if (err < 0){
+ if (err < 0) {
pr_err("Can't allocate a major number (%d) for kpc_dma (err = %d)\n", KPC_DMA_CHAR_MAJOR, err);
goto fail_chrdev_register;
}
assigned_major_num = err;
-
+
kpc_dma_class = class_create(THIS_MODULE, "kpc_dma");
err = PTR_ERR(kpc_dma_class);
- if (IS_ERR(kpc_dma_class)){
+ if (IS_ERR(kpc_dma_class)) {
pr_err("Can't create class kpc_dma (err = %d)\n", err);
goto fail_class_create;
}
-
+
err = platform_driver_register(&kpc_dma_plat_driver_i);
- if (err){
+ if (err) {
pr_err("Can't register platform driver for kpc_dma (err = %d)\n", err);
goto fail_platdriver_register;
}
-
+
return err;
-
- fail_platdriver_register:
+
+fail_platdriver_register:
class_destroy(kpc_dma_class);
- fail_class_create:
+fail_class_create:
__unregister_chrdev(KPC_DMA_CHAR_MAJOR, 0, KPC_DMA_NUM_MINORS, "kpc_dma");
- fail_chrdev_register:
+fail_chrdev_register:
return err;
}
module_init(kpc_dma_driver_init);
static
-void __exit kpc_dma_driver_exit(void)
+void __exit kpc_dma_driver_exit(void)
{
platform_driver_unregister(&kpc_dma_plat_driver_i);
class_destroy(kpc_dma_class);
#include <linux/bitops.h>
#include "../kpc.h"
-
struct kp2000_device;
struct kpc_dma_device {
struct list_head list;
struct device *kpc_dma_dev;
struct kobject kobj;
char name[16];
-
+
int dir; // DMA_FROM_DEVICE || DMA_TO_DEVICE
struct mutex sem;
unsigned int irq;
struct work_struct irq_work;
-
+
atomic_t open_count;
-
+
size_t accumulated_bytes;
u32 accumulated_flags;
-
+
// Descriptor "Pool" housekeeping
u32 desc_pool_cnt;
struct dma_pool *desc_pool;
struct kpc_dma_descriptor *desc_pool_first;
struct kpc_dma_descriptor *desc_pool_last;
-
+
struct kpc_dma_descriptor *desc_next;
struct kpc_dma_descriptor *desc_completed;
};
u64 user_sts;
};
-struct kpc_dma_device * kpc_dma_lookup_device(int minor);
+struct kpc_dma_device *kpc_dma_lookup_device(int minor);
-extern struct file_operations kpc_dma_fops;
+extern const struct file_operations kpc_dma_fops;
#define ENG_CAP_PRESENT 0x00000001
#define ENG_CAP_DIRECTION 0x00000002
unsigned char flags;
struct kiocb *kcb;
size_t len;
-
+
unsigned int page_count;
struct page **user_pages;
struct sg_table sgt;
volatile u32 DescSystemAddrLS;
volatile u32 DescSystemAddrMS;
volatile u32 DescNextDescPtr;
-
+
dma_addr_t MyDMAAddr;
struct kpc_dma_descriptor *Next;
-
+
struct aio_cb_data *acd;
} __attribute__((packed));
// DescControlFlags:
{
writel(value, eng->eng_regs + 1);
}
+
static inline
u32 GetEngineControl(struct kpc_dma_device *eng)
{
return readl(eng->eng_regs + 1);
}
+
static inline
void SetClearEngineControl(struct kpc_dma_device *eng, u32 set_bits, u32 clear_bits)
{
u32 val = GetEngineControl(eng);
+
val |= set_bits;
val &= ~clear_bits;
WriteEngineControl(eng, val);
}
static inline
-void SetEngineNextPtr(struct kpc_dma_device *eng, struct kpc_dma_descriptor * desc)
+void SetEngineNextPtr(struct kpc_dma_device *eng, struct kpc_dma_descriptor *desc)
{
writel(desc->MyDMAAddr, eng->eng_regs + 2);
}
+
static inline
-void SetEngineSWPtr(struct kpc_dma_device *eng, struct kpc_dma_descriptor * desc)
+void SetEngineSWPtr(struct kpc_dma_device *eng, struct kpc_dma_descriptor *desc)
{
writel(desc->MyDMAAddr, eng->eng_regs + 3);
}
+
static inline
void ClearEngineCompletePtr(struct kpc_dma_device *eng)
{
writel(0, eng->eng_regs + 4);
}
+
static inline
u32 GetEngineCompletePtr(struct kpc_dma_device *eng)
{
mutex_unlock(&eng->sem);
}
-
/// Shared Functions
void start_dma_engine(struct kpc_dma_device *eng);
int setup_dma_engine(struct kpc_dma_device *eng, u32 desc_cnt);
+++ /dev/null
-# SPDX-License-Identifier: GPL-2.0
-
-obj-m := kpc2000_i2c.o
-kpc2000_i2c-objs := i2c_driver.o fileops.o
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0+
-#if 0
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h> /* printk() */
-#include <linux/slab.h> /* kmalloc() */
-#include <linux/fs.h> /* everything... */
-#include <linux/errno.h> /* error codes */
-#include <linux/types.h> /* size_t */
-#include <linux/cdev.h>
-#include <asm/uaccess.h> /* copy_*_user */
-
-#include "i2c_driver.h"
-
-int i2c_cdev_open(struct inode *inode, struct file *filp)
-{
- struct i2c_device *lddev;
-
- if(NULL == inode) {
- //printk(KERN_WARNING "<pl_i2c> i2c_cdev_open: inode is a NULL pointer\n");
- DBG_PRINT(KERN_WARNING, "i2c_cdev_open: inode is a NULL pointer\n");
- return -EINVAL;
- }
- if(NULL == filp) {
- //printk(KERN_WARNING "<pl_i2c> i2c_cdev_open: filp is a NULL pointer\n");
- DBG_PRINT(KERN_WARNING, "i2c_cdev_open: filp is a NULL pointer\n");
- return -EINVAL;
- }
-
- lddev = container_of(inode->i_cdev, struct i2c_device, cdev);
- //printk(KERN_DEBUG "<pl_i2c> i2c_cdev_open(filp = [%p], lddev = [%p])\n", filp, lddev);
- DBG_PRINT(KERN_DEBUG, "i2c_cdev_open(filp = [%p], lddev = [%p])\n", filp, lddev);
-
- filp->private_data = lddev; /* so other methods can access it */
-
- return 0; /* success */
-}
-
-int i2c_cdev_close(struct inode *inode, struct file *filp)
-{
- struct i2c_device *lddev;
-
- if(NULL == inode) {
- //printk(KERN_WARNING "<pl_i2c> i2c_cdev_close: inode is a NULL pointer\n");
- DBG_PRINT(KERN_WARNING, "i2c_cdev_close: inode is a NULL pointer\n");
- return -EINVAL;
- }
- if(NULL == filp) {
- //printk(KERN_WARNING "<pl_i2c> i2c_cdev_close: filp is a NULL pointer\n");
- DBG_PRINT(KERN_WARNING, "i2c_cdev_close: filp is a NULL pointer\n");
- return -EINVAL;
- }
-
- lddev = filp->private_data;
- //printk(KERN_DEBUG "<pl_i2c> i2c_cdev_close(filp = [%p], lddev = [%p])\n", filp, lddev);
- DBG_PRINT(KERN_DEBUG, "i2c_cdev_close(filp = [%p], lddev = [%p])\n", filp, lddev);
-
- return 0;
-}
-
-ssize_t i2c_cdev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
-{
- size_t copy;
- ssize_t ret = 0;
- int err = 0;
- u64 read_val;
- char tmp_buf[48] = { 0 };
- struct i2c_device *lddev = filp->private_data;
-
- if(NULL == filp) {
- //printk(KERN_WARNING "<pl_i2c> i2c_cdev_read: filp is a NULL pointer\n");
- DBG_PRINT(KERN_WARNING, "i2c_cdev_read: filp is a NULL pointer\n");
- return -EINVAL;
- }
- if(NULL == buf) {
- //printk(KERN_WARNING "<pl_i2c> i2c_cdev_read: buf is a NULL pointer\n");
- DBG_PRINT(KERN_WARNING, "i2c_cdev_read: buf is a NULL pointer\n");
- return -EINVAL;
- }
- if(NULL == f_pos) {
- //printk(KERN_WARNING "<pl_i2c> i2c_cdev_read: f_pos is a NULL pointer\n");
- DBG_PRINT(KERN_WARNING, "i2c_cdev_read: f_pos is a NULL pointer\n");
- return -EINVAL;
- }
-
- if(count < sizeof(tmp_buf)) {
- //printk(KERN_INFO "<pl_i2c> i2c_cdev_read: buffer is too small (count = %d, should be at least %d bytes)\n", (int)count, (int)sizeof(tmp_buf));
- DBG_PRINT(KERN_INFO, "i2c_cdev_read: buffer is too small (count = %d, should be at least %d bytes)\n", (int)count, (int)sizeof(tmp_buf));
- return -EINVAL;
- }
- if(((*f_pos * 8) + lddev->pldev->resource[0].start) > lddev->pldev->resource[0].end) {
- //printk(KERN_INFO "<pl_i2c> i2c_cdev_read: bad read addr %016llx\n", (*f_pos * 8) + lddev->pldev->resource[0].start);
- DBG_PRINT(KERN_INFO, "i2c_cdev_read: bad read addr %016llx\n", (*f_pos * 8) + lddev->pldev->resource[0].start);
- //printk(KERN_INFO "<pl_i2c> i2c_cdev_read: addr end %016llx\n", lddev->pldev->resource[0].end);
- DBG_PRINT(KERN_INFO, "i2c_cdev_read: addr end %016llx\n", lddev->pldev->resource[0].end);
- //printk(KERN_INFO "<pl_i2c> i2c_cdev_read: EOF reached\n");
- DBG_PRINT(KERN_INFO, "i2c_cdev_read: EOF reached\n");
- return 0;
- }
-
- down_read(&lddev->rw_sem);
-
- read_val = *(lddev->regs + *f_pos);
- copy = clamp_t(size_t, count, 1, sizeof(tmp_buf));
- copy = scnprintf(tmp_buf, copy, "reg: 0x%x val: 0x%llx\n", (unsigned int)*f_pos, read_val);
- err = copy_to_user(buf, tmp_buf, copy);
- if(err) {
- //printk(KERN_INFO "<pl_i2c> i2c_cdev_read: could not copy to user (err = %d)\n", err);
- DBG_PRINT(KERN_INFO, "i2c_cdev_read: could not copy to user (err = %d)\n", err);
- return -EINVAL;
- }
-
- ret = (ssize_t)copy;
- (*f_pos)++;
-
- up_read(&lddev->rw_sem);
-
- return ret;
-}
-
-ssize_t i2c_cdev_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
-{
- u8 reg;
- u8 val;
- char tmp[8] = { 0 };
- struct i2c_device *lddev = filp->private_data;
-
- if(NULL == filp) {
- //printk(KERN_WARNING "<pl_i2c> i2c_cdev_write: filp is a NULL pointer\n");
- DBG_PRINT(KERN_WARNING, "i2c_cdev_write: filp is a NULL pointer\n");
- return -EINVAL;
- }
- if(NULL == buf) {
- //printk(KERN_WARNING "<pl_i2c> i2c_cdev_write: buf is a NULL pointer\n");
- DBG_PRINT(KERN_WARNING, "i2c_cdev_write: buf is a NULL pointer\n");
- return -EINVAL;
- }
- if(NULL == f_pos) {
- //printk(KERN_WARNING "<pl_i2c> i2c_cdev_write: f_pos is a NULL pointer\n");
- DBG_PRINT(KERN_WARNING, "i2c_cdev_write: f_pos is a NULL pointer\n");
- return -EINVAL;
- }
-
- //printk(KERN_DEBUG "<pl_i2c> i2c_cdev_write(filp = [%p], lddev = [%p])\n", filp, lddev);
- DBG_PRINT(KERN_DEBUG, "i2c_cdev_write(filp = [%p], lddev = [%p])\n", filp, lddev);
-
- down_write(&lddev->rw_sem);
-
- if(count >= 2) {
- if(copy_from_user(tmp, buf, 2)) {
- return -EFAULT;
- }
-
- reg = tmp[0] - '0';
- val = tmp[1] - '0';
-
- //printk(KERN_DEBUG " reg = %d val = %d\n", reg, val);
- DBG_PRINT(KERN_DEBUG, " reg = %d val = %d\n", reg, val);
-
- if(reg >= 0 && reg < 16) {
- //printk(KERN_DEBUG " Writing 0x%x to %p\n", val, lddev->regs + reg);
- DBG_PRINT(KERN_DEBUG, " Writing 0x%x to %p\n", val, lddev->regs + reg);
- *(lddev->regs + reg) = val;
- }
- }
-
- (*f_pos)++;
-
- up_write(&lddev->rw_sem);
-
- return count;
-}
-
-struct file_operations i2c_fops = {
- .owner = THIS_MODULE,
- .open = i2c_cdev_open,
- .release = i2c_cdev_close,
- .read = i2c_cdev_read,
- .write = i2c_cdev_write,
-};
-#endif
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0+
-/* Copyright (c) 2014-2018 Daktronics,
- Matt Sickler <matt.sickler@daktronics.com>,
- Jordon Hofer <jordon.hofer@daktronics.com>
- Adapted i2c-i801.c for use with Kadoka hardware.
- Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
- Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
- <mdsxyz123@yahoo.com>
- Copyright (C) 2007 - 2012 Jean Delvare <khali@linux-fr.org>
- Copyright (C) 2010 Intel Corporation,
- David Woodhouse <dwmw2@infradead.org>
-*/
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <asm/io.h>
-#include <linux/io-64-nonatomic-lo-hi.h>
-#include <linux/export.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/fs.h>
-#include <linux/rwsem.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include "../kpc.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Matt.Sickler@Daktronics.com");
-MODULE_SOFTDEP("pre: i2c-dev");
-
-struct i2c_device {
- unsigned long smba;
- struct i2c_adapter adapter;
- struct platform_device *pldev;
- struct rw_semaphore rw_sem;
- unsigned int features;
-};
-
-/*****************************
- *** Part 1 - i2c Handlers ***
- *****************************/
-
-#define REG_SIZE 8
-
-/* I801 SMBus address offsets */
-#define SMBHSTSTS(p) ((0 * REG_SIZE) + (p)->smba)
-#define SMBHSTCNT(p) ((2 * REG_SIZE) + (p)->smba)
-#define SMBHSTCMD(p) ((3 * REG_SIZE) + (p)->smba)
-#define SMBHSTADD(p) ((4 * REG_SIZE) + (p)->smba)
-#define SMBHSTDAT0(p) ((5 * REG_SIZE) + (p)->smba)
-#define SMBHSTDAT1(p) ((6 * REG_SIZE) + (p)->smba)
-#define SMBBLKDAT(p) ((7 * REG_SIZE) + (p)->smba)
-#define SMBPEC(p) ((8 * REG_SIZE) + (p)->smba) /* ICH3 and later */
-#define SMBAUXSTS(p) ((12 * REG_SIZE) + (p)->smba) /* ICH4 and later */
-#define SMBAUXCTL(p) ((13 * REG_SIZE) + (p)->smba) /* ICH4 and later */
-
-/* PCI Address Constants */
-#define SMBBAR 4
-#define SMBHSTCFG 0x040
-
-/* Host configuration bits for SMBHSTCFG */
-#define SMBHSTCFG_HST_EN 1
-#define SMBHSTCFG_SMB_SMI_EN 2
-#define SMBHSTCFG_I2C_EN 4
-
-/* Auxiliary control register bits, ICH4+ only */
-#define SMBAUXCTL_CRC 1
-#define SMBAUXCTL_E32B 2
-
-/* kill bit for SMBHSTCNT */
-#define SMBHSTCNT_KILL 2
-
-/* Other settings */
-#define MAX_RETRIES 400
-#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
-
-/* I801 command constants */
-#define I801_QUICK 0x00
-#define I801_BYTE 0x04
-#define I801_BYTE_DATA 0x08
-#define I801_WORD_DATA 0x0C
-#define I801_PROC_CALL 0x10 /* unimplemented */
-#define I801_BLOCK_DATA 0x14
-#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
-#define I801_BLOCK_LAST 0x34
-#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */
-#define I801_START 0x40
-#define I801_PEC_EN 0x80 /* ICH3 and later */
-
-/* I801 Hosts Status register bits */
-#define SMBHSTSTS_BYTE_DONE 0x80
-#define SMBHSTSTS_INUSE_STS 0x40
-#define SMBHSTSTS_SMBALERT_STS 0x20
-#define SMBHSTSTS_FAILED 0x10
-#define SMBHSTSTS_BUS_ERR 0x08
-#define SMBHSTSTS_DEV_ERR 0x04
-#define SMBHSTSTS_INTR 0x02
-#define SMBHSTSTS_HOST_BUSY 0x01
-
-#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | SMBHSTSTS_INTR)
-
-/* Older devices have their ID defined in <linux/pci_ids.h> */
-#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22
-/* Patsburg also has three 'Integrated Device Function' SMBus controllers */
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72
-#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22
-#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330
-#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30
-#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22
-#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22
-
-
-#define FEATURE_SMBUS_PEC (1 << 0)
-#define FEATURE_BLOCK_BUFFER (1 << 1)
-#define FEATURE_BLOCK_PROC (1 << 2)
-#define FEATURE_I2C_BLOCK_READ (1 << 3)
-/* Not really a feature, but it's convenient to handle it as such */
-#define FEATURE_IDF (1 << 15)
-
-static unsigned int disable_features;
-module_param(disable_features, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(disable_features, "Disable selected driver features");
-
-// FIXME!
-#undef inb_p
-#define inb_p(a) readq((void*)a)
-#undef outb_p
-#define outb_p(d,a) writeq(d,(void*)a)
-
-/* 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)
-{
- int status;
-
- dev_dbg(&priv->adapter.dev, "i801_check_pre\n");
-
- status = inb_p(SMBHSTSTS(priv));
- if (status & SMBHSTSTS_HOST_BUSY) {
- dev_err(&priv->adapter.dev, "SMBus is busy, can't use it! (status=%x)\n", status);
- return -EBUSY;
- }
-
- status &= STATUS_FLAGS;
- if (status) {
- //dev_dbg(&priv->adapter.dev, "Clearing status flags (%02x)\n", status);
- outb_p(status, SMBHSTSTS(priv));
- status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
- if (status) {
- dev_err(&priv->adapter.dev, "Failed clearing status flags (%02x)\n", status);
- return -EBUSY;
- }
- }
- return 0;
-}
-
-/* Convert the status register to an error code, and clear it. */
-static int i801_check_post(struct i2c_device *priv, int status, int timeout)
-{
- int result = 0;
-
- dev_dbg(&priv->adapter.dev, "i801_check_post\n");
-
- /* If the SMBus is still busy, we give up */
- if (timeout) {
- dev_err(&priv->adapter.dev, "Transaction timeout\n");
- /* try to stop the current command */
- dev_dbg(&priv->adapter.dev, "Terminating the current operation\n");
- outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL, SMBHSTCNT(priv));
- usleep_range(1000, 2000);
- outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL), SMBHSTCNT(priv));
-
- /* Check if it worked */
- status = inb_p(SMBHSTSTS(priv));
- if ((status & SMBHSTSTS_HOST_BUSY) || !(status & SMBHSTSTS_FAILED)) {
- dev_err(&priv->adapter.dev, "Failed terminating the transaction\n");
- }
- outb_p(STATUS_FLAGS, SMBHSTSTS(priv));
- return -ETIMEDOUT;
- }
-
- if (status & SMBHSTSTS_FAILED) {
- result = -EIO;
- dev_err(&priv->adapter.dev, "Transaction failed\n");
- }
- if (status & SMBHSTSTS_DEV_ERR) {
- result = -ENXIO;
- dev_dbg(&priv->adapter.dev, "No response\n");
- }
- if (status & SMBHSTSTS_BUS_ERR) {
- result = -EAGAIN;
- dev_dbg(&priv->adapter.dev, "Lost arbitration\n");
- }
-
- if (result) {
- /* Clear error flags */
- outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv));
- status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
- if (status) {
- dev_warn(&priv->adapter.dev, "Failed clearing status flags at end of transaction (%02x)\n", status);
- }
- }
-
- return result;
-}
-
-static int i801_transaction(struct i2c_device *priv, int xact)
-{
- int status;
- int result;
- int timeout = 0;
-
- dev_dbg(&priv->adapter.dev, "i801_transaction\n");
-
- result = i801_check_pre(priv);
- if (result < 0) {
- return result;
- }
- /* the current contents of SMBHSTCNT can be overwritten, since PEC,
- * INTREN, SMBSCMD are passed in xact */
- outb_p(xact | I801_START, SMBHSTCNT(priv));
-
- /* We will always wait for a fraction of a second! */
- do {
- usleep_range(250, 500);
- status = inb_p(SMBHSTSTS(priv));
- } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_RETRIES));
-
- result = i801_check_post(priv, status, timeout > MAX_RETRIES);
- if (result < 0) {
- return result;
- }
-
- outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
- return 0;
-}
-
-/* wait for INTR bit as advised by Intel */
-static void i801_wait_hwpec(struct i2c_device *priv)
-{
- int timeout = 0;
- int status;
-
- dev_dbg(&priv->adapter.dev, "i801_wait_hwpec\n");
-
- do {
- usleep_range(250, 500);
- status = inb_p(SMBHSTSTS(priv));
- } while ((!(status & SMBHSTSTS_INTR)) && (timeout++ < MAX_RETRIES));
-
- if (timeout > MAX_RETRIES) {
- dev_dbg(&priv->adapter.dev, "PEC Timeout!\n");
- }
-
- outb_p(status, SMBHSTSTS(priv));
-}
-
-static int i801_block_transaction_by_block(struct i2c_device *priv, union i2c_smbus_data *data, char read_write, int hwpec)
-{
- int i, len;
- int status;
-
- dev_dbg(&priv->adapter.dev, "i801_block_transaction_by_block\n");
-
- inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */
-
- /* Use 32-byte buffer to process this transaction */
- if (read_write == I2C_SMBUS_WRITE) {
- len = data->block[0];
- outb_p(len, SMBHSTDAT0(priv));
- for (i = 0; i < len; i++) {
- outb_p(data->block[i+1], SMBBLKDAT(priv));
- }
- }
-
- status = i801_transaction(priv, I801_BLOCK_DATA | ENABLE_INT9 | I801_PEC_EN * hwpec);
- if (status) {
- return status;
- }
-
- if (read_write == I2C_SMBUS_READ) {
- len = inb_p(SMBHSTDAT0(priv));
- if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
- return -EPROTO;
- }
-
- data->block[0] = len;
- for (i = 0; i < len; i++) {
- data->block[i + 1] = inb_p(SMBBLKDAT(priv));
- }
- }
- return 0;
-}
-
-static int i801_block_transaction_byte_by_byte(struct i2c_device *priv, union i2c_smbus_data *data, char read_write, int command, int hwpec)
-{
- int i, len;
- int smbcmd;
- int status;
- int result;
- int timeout;
-
- dev_dbg(&priv->adapter.dev, "i801_block_transaction_byte_by_byte\n");
-
- result = i801_check_pre(priv);
- if (result < 0) {
- return result;
- }
-
- len = data->block[0];
-
- if (read_write == I2C_SMBUS_WRITE) {
- outb_p(len, SMBHSTDAT0(priv));
- outb_p(data->block[1], SMBBLKDAT(priv));
- }
-
- for (i = 1; i <= len; i++) {
- if (i == len && read_write == I2C_SMBUS_READ) {
- if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
- smbcmd = I801_I2C_BLOCK_LAST;
- } else {
- smbcmd = I801_BLOCK_LAST;
- }
- } else {
- if (command == I2C_SMBUS_I2C_BLOCK_DATA && read_write == I2C_SMBUS_READ) {
- smbcmd = I801_I2C_BLOCK_DATA;
- } else {
- smbcmd = I801_BLOCK_DATA;
- }
- }
- outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT(priv));
-
- if (i == 1) {
- outb_p(inb(SMBHSTCNT(priv)) | I801_START, SMBHSTCNT(priv));
- }
- /* We will always wait for a fraction of a second! */
- timeout = 0;
- do {
- usleep_range(250, 500);
- status = inb_p(SMBHSTSTS(priv));
- } while ((!(status & SMBHSTSTS_BYTE_DONE)) && (timeout++ < MAX_RETRIES));
-
- result = i801_check_post(priv, status, timeout > MAX_RETRIES);
- if (result < 0) {
- return result;
- }
- if (i == 1 && read_write == I2C_SMBUS_READ && command != I2C_SMBUS_I2C_BLOCK_DATA) {
- len = inb_p(SMBHSTDAT0(priv));
- if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
- dev_err(&priv->adapter.dev, "Illegal SMBus block read size %d\n", len);
- /* Recover */
- while (inb_p(SMBHSTSTS(priv)) & SMBHSTSTS_HOST_BUSY) {
- outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
- }
- outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
- return -EPROTO;
- }
- data->block[0] = len;
- }
-
- /* Retrieve/store value in SMBBLKDAT */
- if (read_write == I2C_SMBUS_READ) {
- data->block[i] = inb_p(SMBBLKDAT(priv));
- }
- if (read_write == I2C_SMBUS_WRITE && i+1 <= len) {
- outb_p(data->block[i+1], SMBBLKDAT(priv));
- }
- /* signals SMBBLKDAT ready */
- outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS(priv));
- }
-
- return 0;
-}
-
-static int i801_set_block_buffer_mode(struct i2c_device *priv)
-{
- dev_dbg(&priv->adapter.dev, "i801_set_block_buffer_mode\n");
-
- outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv));
- if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0) {
- return -EIO;
- }
- return 0;
-}
-
-/* Block transaction function */
-static int i801_block_transaction(struct i2c_device *priv, union i2c_smbus_data *data, char read_write, int command, int hwpec)
-{
- int result = 0;
- //unsigned char hostc;
-
- dev_dbg(&priv->adapter.dev, "i801_block_transaction\n");
-
- if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
- if (read_write == I2C_SMBUS_WRITE) {
- /* set I2C_EN bit in configuration register */
- //TODO: Figure out the right thing to do here...
- //pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
- //pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc | SMBHSTCFG_I2C_EN);
- } else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) {
- dev_err(&priv->adapter.dev, "I2C block read is unsupported!\n");
- return -EOPNOTSUPP;
- }
- }
-
- if (read_write == I2C_SMBUS_WRITE || command == I2C_SMBUS_I2C_BLOCK_DATA) {
- if (data->block[0] < 1) {
- data->block[0] = 1;
- }
- if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
- data->block[0] = I2C_SMBUS_BLOCK_MAX;
- }
- } else {
- data->block[0] = 32; /* max for SMBus block reads */
- }
-
- /* Experience has shown that the block buffer can only be used for
- SMBus (not I2C) block transactions, even though the datasheet
- doesn't mention this limitation. */
- if ((priv->features & FEATURE_BLOCK_BUFFER) && command != I2C_SMBUS_I2C_BLOCK_DATA && i801_set_block_buffer_mode(priv) == 0) {
- result = i801_block_transaction_by_block(priv, data, read_write, hwpec);
- } else {
- result = i801_block_transaction_byte_by_byte(priv, data, read_write, command, hwpec);
- }
- if (result == 0 && hwpec) {
- i801_wait_hwpec(priv);
- }
- if (command == I2C_SMBUS_I2C_BLOCK_DATA && read_write == I2C_SMBUS_WRITE) {
- /* restore saved configuration register value */
- //TODO: Figure out the right thing to do here...
- //pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc);
- }
- return result;
-}
-
-/* Return negative errno on error. */
-static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data)
-{
- int hwpec;
- int block = 0;
- int ret, xact = 0;
- struct i2c_device *priv = i2c_get_adapdata(adap);
-
- dev_dbg(&priv->adapter.dev, "i801_access (addr=%0d) flags=%x read_write=%x command=%x size=%x",
- addr, flags, read_write, command, size );
-
- hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA;
-
- switch (size) {
- case I2C_SMBUS_QUICK:
- dev_dbg(&priv->adapter.dev, " [acc] SMBUS_QUICK\n");
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
- xact = I801_QUICK;
- break;
- case I2C_SMBUS_BYTE:
- dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BYTE\n");
-
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
- if (read_write == I2C_SMBUS_WRITE) {
- outb_p(command, SMBHSTCMD(priv));
- }
- xact = I801_BYTE;
- break;
- case I2C_SMBUS_BYTE_DATA:
- dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BYTE_DATA\n");
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
- outb_p(command, SMBHSTCMD(priv));
- if (read_write == I2C_SMBUS_WRITE) {
- outb_p(data->byte, SMBHSTDAT0(priv));
- }
- xact = I801_BYTE_DATA;
- break;
- case I2C_SMBUS_WORD_DATA:
- dev_dbg(&priv->adapter.dev, " [acc] SMBUS_WORD_DATA\n");
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
- outb_p(command, SMBHSTCMD(priv));
- if (read_write == I2C_SMBUS_WRITE) {
- outb_p(data->word & 0xff, SMBHSTDAT0(priv));
- outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv));
- }
- xact = I801_WORD_DATA;
- break;
- case I2C_SMBUS_BLOCK_DATA:
- dev_dbg(&priv->adapter.dev, " [acc] SMBUS_BLOCK_DATA\n");
- outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD(priv));
- outb_p(command, SMBHSTCMD(priv));
- block = 1;
- break;
- case I2C_SMBUS_I2C_BLOCK_DATA:
- dev_dbg(&priv->adapter.dev, " [acc] SMBUS_I2C_BLOCK_DATA\n");
- /* NB: page 240 of ICH5 datasheet shows that the R/#W
- * bit should be cleared here, even when reading */
- outb_p((addr & 0x7f) << 1, SMBHSTADD(priv));
- if (read_write == I2C_SMBUS_READ) {
- /* NB: page 240 of ICH5 datasheet also shows
- * that DATA1 is the cmd field when reading */
- outb_p(command, SMBHSTDAT1(priv));
- } else {
- outb_p(command, SMBHSTCMD(priv));
- }
- block = 1;
- break;
- default:
- dev_dbg(&priv->adapter.dev, " [acc] Unsupported transaction %d\n", size);
- return -EOPNOTSUPP;
- }
-
- if (hwpec) { /* enable/disable hardware PEC */
- dev_dbg(&priv->adapter.dev, " [acc] hwpec: yes\n");
- outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv));
- } else {
- dev_dbg(&priv->adapter.dev, " [acc] hwpec: no\n");
- outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC), SMBAUXCTL(priv));
- }
-
- if (block) {
- //ret = 0;
- dev_dbg(&priv->adapter.dev, " [acc] block: yes\n");
- ret = i801_block_transaction(priv, data, read_write, size, hwpec);
- } else {
- dev_dbg(&priv->adapter.dev, " [acc] block: no\n");
- ret = i801_transaction(priv, xact | ENABLE_INT9);
- }
-
- /* Some BIOSes don't like it when PEC is enabled at reboot or resume
- time, so we forcibly disable it after every transaction. Turn off
- E32B for the same reason. */
- if (hwpec || block) {
- dev_dbg(&priv->adapter.dev, " [acc] hwpec || block\n");
- outb_p(inb_p(SMBAUXCTL(priv)) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
- }
- if (block) {
- dev_dbg(&priv->adapter.dev, " [acc] block\n");
- return ret;
- }
- if (ret) {
- dev_dbg(&priv->adapter.dev, " [acc] ret %d\n", ret);
- return ret;
- }
- if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) {
- dev_dbg(&priv->adapter.dev, " [acc] I2C_SMBUS_WRITE || I801_QUICK -> ret 0\n");
- return 0;
- }
-
- switch (xact & 0x7f) {
- case I801_BYTE: /* Result put in SMBHSTDAT0 */
- case I801_BYTE_DATA:
- dev_dbg(&priv->adapter.dev, " [acc] I801_BYTE or I801_BYTE_DATA\n");
- data->byte = inb_p(SMBHSTDAT0(priv));
- break;
- case I801_WORD_DATA:
- dev_dbg(&priv->adapter.dev, " [acc] I801_WORD_DATA\n");
- data->word = inb_p(SMBHSTDAT0(priv)) + (inb_p(SMBHSTDAT1(priv)) << 8);
- break;
- }
- return 0;
-}
-
-
-
-static u32 i801_func(struct i2c_adapter *adapter)
-{
- struct i2c_device *priv = i2c_get_adapdata(adapter);
-
- /* original settings
- u32 f = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
- I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
- ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
- ((priv->features & FEATURE_I2C_BLOCK_READ) ?
- I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0);
- */
-
- // 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 */
-
- 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 _BYTE_DATA _WORD_DATA _PROC_CALL _WRITE_BLOCK_DATA _I2C_BLOCK _PEC */
- return f;
-}
-
-static const struct i2c_algorithm smbus_algorithm = {
- .smbus_xfer = i801_access,
- .functionality = i801_func,
-};
-
-
-
-/********************************
- *** Part 2 - Driver Handlers ***
- ********************************/
-int pi2c_probe(struct platform_device *pldev)
-{
- int err;
- struct i2c_device *priv;
- struct resource *res;
-
- dev_dbg(&pldev->dev, "pi2c_probe(pldev = %p '%s')\n", pldev, pldev->name);
-
- priv = kzalloc(sizeof(struct i2c_device), GFP_KERNEL);
- if (!priv) {
- return -ENOMEM;
- }
-
- i2c_set_adapdata(&priv->adapter, priv);
- priv->adapter.owner = THIS_MODULE;
- priv->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
- priv->adapter.algo = &smbus_algorithm;
-
- res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
- priv->smba = (unsigned long)ioremap_nocache(res->start, resource_size(res));
-
- priv->pldev = pldev;
- pldev->dev.platform_data = priv;
-
- priv->features |= FEATURE_IDF;
- priv->features |= FEATURE_I2C_BLOCK_READ;
- priv->features |= FEATURE_SMBUS_PEC;
- priv->features |= FEATURE_BLOCK_BUFFER;
-
- //init_MUTEX(&lddata->sem);
- init_rwsem(&priv->rw_sem);
-
- /* set up the sysfs linkage to our parent device */
- priv->adapter.dev.parent = &pldev->dev;
-
- /* Retry up to 3 times on lost arbitration */
- priv->adapter.retries = 3;
-
- //snprintf(priv->adapter.name, sizeof(priv->adapter.name), "Fake SMBus I801 adapter at %04lx", priv->smba);
- snprintf(priv->adapter.name, sizeof(priv->adapter.name), "Fake SMBus I801 adapter");
-
- err = i2c_add_adapter(&priv->adapter);
- if (err) {
- dev_err(&priv->adapter.dev, "Failed to add SMBus adapter\n");
- return err;
- }
-
- return 0;
-}
-
-int pi2c_remove(struct platform_device *pldev)
-{
- struct i2c_device *lddev;
- dev_dbg(&pldev->dev, "pi2c_remove(pldev = %p '%s')\n", pldev, pldev->name);
-
- lddev = (struct i2c_device *)pldev->dev.platform_data;
-
- i2c_del_adapter(&lddev->adapter);
-
- //TODO: Figure out the right thing to do here...
- //pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
- //pci_release_region(dev, SMBBAR);
- //pci_set_drvdata(dev, NULL);
-
- //cdev_del(&lddev->cdev);
- if(lddev != 0) {
- kfree(lddev);
- pldev->dev.platform_data = 0;
- }
-
- return 0;
-}
-
-struct platform_driver i2c_plat_driver_i = {
- .probe = pi2c_probe,
- .remove = pi2c_remove,
- .driver = {
- .name = KP_DRIVER_NAME_I2C,
- .owner = THIS_MODULE,
- },
-};
-
-module_platform_driver(i2c_plat_driver_i);
+++ /dev/null
-# SPDX-License-Identifier: GPL-2.0
-
-obj-m += kpc2000_spi.o
-kpc2000_spi-objs := spi_driver.o
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * KP2000 SPI controller driver
- *
- * Copyright (C) 2014-2018 Daktronics
- * Author: Matt Sickler <matt.sickler@daktronics.com>
- * Very loosely based on spi-omap2-mcspi.c
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io-64-nonatomic-lo-hi.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/gcd.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/flash.h>
-#include <linux/mtd/partitions.h>
-
-#include "../kpc.h"
-#include "spi_parts.h"
-
-
-/***************
- * SPI Defines *
- ***************/
-#define KP_SPI_REG_CONFIG 0x0 /* 0x00 */
-#define KP_SPI_REG_STATUS 0x1 /* 0x08 */
-#define KP_SPI_REG_FFCTRL 0x2 /* 0x10 */
-#define KP_SPI_REG_TXDATA 0x3 /* 0x18 */
-#define KP_SPI_REG_RXDATA 0x4 /* 0x20 */
-
-#define KP_SPI_CLK 48000000
-#define KP_SPI_MAX_FIFODEPTH 64
-#define KP_SPI_MAX_FIFOWCNT 0xFFFF
-
-#define KP_SPI_REG_CONFIG_TRM_TXRX 0
-#define KP_SPI_REG_CONFIG_TRM_RX 1
-#define KP_SPI_REG_CONFIG_TRM_TX 2
-
-#define KP_SPI_REG_STATUS_RXS 0x01
-#define KP_SPI_REG_STATUS_TXS 0x02
-#define KP_SPI_REG_STATUS_EOT 0x04
-#define KP_SPI_REG_STATUS_TXFFE 0x10
-#define KP_SPI_REG_STATUS_TXFFF 0x20
-#define KP_SPI_REG_STATUS_RXFFE 0x40
-#define KP_SPI_REG_STATUS_RXFFF 0x80
-
-
-
-/******************
- * SPI Structures *
- ******************/
-struct kp_spi {
- struct spi_master *master;
- u64 __iomem *base;
- unsigned long phys;
- struct device *dev;
- int fifo_depth;
- unsigned int pin_dir:1;
-};
-
-
-struct kp_spi_controller_state {
- void __iomem *base;
- unsigned long phys;
- unsigned char chip_select;
- int word_len;
- s64 conf_cache;
-};
-
-
-union kp_spi_config {
- /* use this to access individual elements */
- struct __attribute__((packed)) spi_config_bitfield {
- unsigned int pha : 1; /* spim_clk Phase */
- unsigned int pol : 1; /* spim_clk Polarity */
- unsigned int epol : 1; /* spim_csx Polarity */
- unsigned int dpe : 1; /* Transmission Enable */
- unsigned int wl : 5; /* Word Length */
- unsigned int : 3;
- unsigned int trm : 2; /* TxRx Mode */
- unsigned int cs : 4; /* Chip Select */
- unsigned int wcnt : 7; /* Word Count */
- unsigned int ffen : 1; /* FIFO Enable */
- unsigned int spi_en : 1; /* SPI Enable */
- unsigned int : 5;
- } bitfield;
- /* use this to grab the whole register */
- u32 reg;
-};
-
-
-
-union kp_spi_status {
- struct __attribute__((packed)) spi_status_bitfield {
- unsigned int rx : 1; /* Rx Status */
- unsigned int tx : 1; /* Tx Status */
- unsigned int eo : 1; /* End of Transfer */
- unsigned int : 1;
- unsigned int txffe : 1; /* Tx FIFO Empty */
- unsigned int txfff : 1; /* Tx FIFO Full */
- unsigned int rxffe : 1; /* Rx FIFO Empty */
- unsigned int rxfff : 1; /* Rx FIFO Full */
- unsigned int : 24;
- } bitfield;
- u32 reg;
-};
-
-
-
-union kp_spi_ffctrl {
- struct __attribute__((packed)) spi_ffctrl_bitfield {
- unsigned int ffstart : 1; /* FIFO Start */
- unsigned int : 31;
- } bitfield;
- u32 reg;
-};
-
-
-
-/***************
- * SPI Helpers *
- ***************/
-static inline int
-kp_spi_bytes_per_word(int word_len)
-{
- if (word_len <= 8){
- return 1;
- }
- else if (word_len <= 16) {
- return 2;
- }
- else { /* word_len <= 32 */
- return 4;
- }
-}
-
-static inline u64
-kp_spi_read_reg(struct kp_spi_controller_state *cs, int idx)
-{
- u64 __iomem *addr = cs->base;
- u64 val;
-
- addr += idx;
- if ((idx == KP_SPI_REG_CONFIG) && (cs->conf_cache >= 0)){
- return cs->conf_cache;
- }
- val = readq((void*)addr);
- return val;
-}
-
-static inline void
-kp_spi_write_reg(struct kp_spi_controller_state *cs, int idx, u64 val)
-{
- u64 __iomem *addr = cs->base;
- addr += idx;
- writeq(val, (void*)addr);
- if (idx == KP_SPI_REG_CONFIG)
- cs->conf_cache = val;
-}
-
-static int
-kp_spi_wait_for_reg_bit(struct kp_spi_controller_state *cs, int idx, unsigned long bit)
-{
- unsigned long timeout;
- timeout = jiffies + msecs_to_jiffies(1000);
- while (!(kp_spi_read_reg(cs, idx) & bit)) {
- if (time_after(jiffies, timeout)) {
- if (!(kp_spi_read_reg(cs, idx) & bit)) {
- return -ETIMEDOUT;
- } else {
- return 0;
- }
- }
- cpu_relax();
- }
- return 0;
-}
-
-static unsigned
-kp_spi_txrx_pio(struct spi_device *spidev, struct spi_transfer *transfer)
-{
- struct kp_spi_controller_state *cs = spidev->controller_state;
- unsigned int count = transfer->len;
- unsigned int c = count;
-
- int i;
- u8 *rx = transfer->rx_buf;
- const u8 *tx = transfer->tx_buf;
- int processed = 0;
-
- if (tx) {
- for (i = 0 ; i < c ; i++) {
- char val = *tx++;
-
- if (kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, KP_SPI_REG_STATUS_TXS) < 0) {
- goto out;
- }
-
- kp_spi_write_reg(cs, KP_SPI_REG_TXDATA, val);
- processed++;
- }
- }
- else if(rx) {
- for (i = 0 ; i < c ; i++) {
- char test=0;
-
- kp_spi_write_reg(cs, KP_SPI_REG_TXDATA, 0x00);
-
- if (kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, KP_SPI_REG_STATUS_RXS) < 0) {
- goto out;
- }
-
- test = kp_spi_read_reg(cs, KP_SPI_REG_RXDATA);
- *rx++ = test;
- processed++;
- }
- }
-
- if (kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, KP_SPI_REG_STATUS_EOT) < 0) {
- //TODO: Figure out how to abort transaction?? This has never happened in practice though...
- }
-
- out:
- return processed;
-}
-
-/*****************
- * SPI Functions *
- *****************/
-static int
-kp_spi_setup(struct spi_device *spidev)
-{
- union kp_spi_config sc;
- struct kp_spi *kpspi = spi_master_get_devdata(spidev->master);
- struct kp_spi_controller_state *cs;
-
- /* setup controller state */
- cs = spidev->controller_state;
- if (!cs) {
- cs = kzalloc(sizeof(*cs), GFP_KERNEL);
- if(!cs) {
- return -ENOMEM;
- }
- cs->base = kpspi->base;
- cs->phys = kpspi->phys;
- cs->chip_select = spidev->chip_select;
- cs->word_len = spidev->bits_per_word;
- cs->conf_cache = -1;
- spidev->controller_state = cs;
- }
-
- /* set config register */
- sc.bitfield.wl = spidev->bits_per_word - 1;
- sc.bitfield.cs = spidev->chip_select;
- sc.bitfield.spi_en = 0;
- sc.bitfield.trm = 0;
- sc.bitfield.ffen = 0;
- kp_spi_write_reg(spidev->controller_state, KP_SPI_REG_CONFIG, sc.reg);
- return 0;
-}
-
-static int
-kp_spi_transfer_one_message(struct spi_master *master, struct spi_message *m)
-{
- struct kp_spi_controller_state *cs;
- struct spi_device *spidev;
- struct kp_spi *kpspi;
- struct spi_transfer *transfer;
- union kp_spi_config sc;
- int status = 0;
-
- spidev = m->spi;
- kpspi = spi_master_get_devdata(master);
- m->actual_length = 0;
- m->status = 0;
-
- cs = spidev->controller_state;
-
- /* reject invalid messages and transfers */
- if (list_empty(&m->transfers)) {
- return -EINVAL;
- }
-
- /* validate input */
- list_for_each_entry(transfer, &m->transfers, transfer_list) {
- const void *tx_buf = transfer->tx_buf;
- void *rx_buf = transfer->rx_buf;
- unsigned len = transfer->len;
-
- if (transfer->speed_hz > KP_SPI_CLK || (len && !(rx_buf || tx_buf))) {
- dev_dbg(kpspi->dev, " transfer: %d Hz, %d %s%s, %d bpw\n",
- transfer->speed_hz,
- len,
- tx_buf ? "tx" : "",
- rx_buf ? "rx" : "",
- transfer->bits_per_word);
- dev_dbg(kpspi->dev, " transfer -EINVAL\n");
- return -EINVAL;
- }
- if (transfer->speed_hz && (transfer->speed_hz < (KP_SPI_CLK >> 15))) {
- dev_dbg(kpspi->dev, "speed_hz %d below minimum %d Hz\n",
- transfer->speed_hz,
- KP_SPI_CLK >> 15);
- dev_dbg(kpspi->dev, " speed_hz -EINVAL\n");
- return -EINVAL;
- }
- }
-
- /* assert chip select to start the sequence*/
- sc.reg = kp_spi_read_reg(cs, KP_SPI_REG_CONFIG);
- sc.bitfield.spi_en = 1;
- kp_spi_write_reg(cs, KP_SPI_REG_CONFIG, sc.reg);
-
- /* work */
- if (kp_spi_wait_for_reg_bit(cs, KP_SPI_REG_STATUS, KP_SPI_REG_STATUS_EOT) < 0) {
- dev_info(kpspi->dev, "EOT timed out\n");
- goto out;
- }
-
- /* do the transfers for this message */
- list_for_each_entry(transfer, &m->transfers, transfer_list) {
- if (transfer->tx_buf == NULL && transfer->rx_buf == NULL && transfer->len) {
- status = -EINVAL;
- break;
- }
-
- /* transfer */
- if (transfer->len) {
- unsigned int word_len = spidev->bits_per_word;
- unsigned count;
-
- /* set up the transfer... */
- sc.reg = kp_spi_read_reg(cs, KP_SPI_REG_CONFIG);
-
- /* ...direction */
- if (transfer->tx_buf) {
- sc.bitfield.trm = KP_SPI_REG_CONFIG_TRM_TX;
- }
- else if (transfer->rx_buf) {
- sc.bitfield.trm = KP_SPI_REG_CONFIG_TRM_RX;
- }
-
- /* ...word length */
- if (transfer->bits_per_word) {
- word_len = transfer->bits_per_word;
- }
- cs->word_len = word_len;
- sc.bitfield.wl = word_len-1;
-
- /* ...chip select */
- sc.bitfield.cs = spidev->chip_select;
-
- /* ...and write the new settings */
- kp_spi_write_reg(cs, KP_SPI_REG_CONFIG, sc.reg);
-
- /* do the transfer */
- count = kp_spi_txrx_pio(spidev, transfer);
- m->actual_length += count;
-
- if (count != transfer->len) {
- status = -EIO;
- break;
- }
- }
-
- if (transfer->delay_usecs) {
- udelay(transfer->delay_usecs);
- }
- }
-
- /* de-assert chip select to end the sequence */
- sc.reg = kp_spi_read_reg(cs, KP_SPI_REG_CONFIG);
- sc.bitfield.spi_en = 0;
- kp_spi_write_reg(cs, KP_SPI_REG_CONFIG, sc.reg);
-
- out:
- /* done work */
- spi_finalize_current_message(master);
- return 0;
-}
-
-static void
-kp_spi_cleanup(struct spi_device *spidev)
-{
- struct kp_spi_controller_state *cs = spidev->controller_state;
- if (cs) {
- kfree(cs);
- }
-}
-
-
-
-/******************
- * Probe / Remove *
- ******************/
-static int
-kp_spi_probe(struct platform_device *pldev)
-{
- struct kpc_core_device_platdata *drvdata;
- struct spi_master *master;
- struct kp_spi *kpspi;
- struct resource *r;
- int status = 0;
- int i;
-
- drvdata = pldev->dev.platform_data;
- if (!drvdata){
- dev_err(&pldev->dev, "kp_spi_probe: platform_data is NULL!\n");
- return -ENODEV;
- }
-
- master = spi_alloc_master(&pldev->dev, sizeof(struct kp_spi));
- if (master == NULL) {
- dev_err(&pldev->dev, "kp_spi_probe: master allocation failed\n");
- return -ENOMEM;
- }
-
- /* set up the spi functions */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
- master->bits_per_word_mask = (unsigned int)SPI_BPW_RANGE_MASK(4, 32);
- master->setup = kp_spi_setup;
- master->transfer_one_message = kp_spi_transfer_one_message;
- master->cleanup = kp_spi_cleanup;
-
- platform_set_drvdata(pldev, master);
-
- kpspi = spi_master_get_devdata(master);
- kpspi->master = master;
- kpspi->dev = &pldev->dev;
-
- master->num_chipselect = 4;
- if (pldev->id != -1) {
- master->bus_num = pldev->id;
- }
- kpspi->pin_dir = 0;
-
- r = platform_get_resource(pldev, IORESOURCE_MEM, 0);
- if (r == NULL) {
- dev_err(&pldev->dev, "kp_spi_probe: Unable to get platform resources\n");
- status = -ENODEV;
- goto free_master;
- }
-
- kpspi->phys = (unsigned long)ioremap_nocache(r->start, resource_size(r));
- kpspi->base = (u64 __iomem *)kpspi->phys;
-
- status = spi_register_master(master);
- if (status < 0) {
- dev_err(&pldev->dev, "Unable to register SPI device\n");
- goto free_master;
- }
-
- /* register the slave boards */
- #define NEW_SPI_DEVICE_FROM_BOARD_INFO_TABLE(table) \
- for (i = 0 ; i < ARRAY_SIZE(table) ; i++) { \
- spi_new_device(master, &(table[i])); \
- }
-
- switch ((drvdata->card_id & 0xFFFF0000) >> 16){
- case PCI_DEVICE_ID_DAKTRONICS_KADOKA_P2KR0:
- NEW_SPI_DEVICE_FROM_BOARD_INFO_TABLE(p2kr0_board_info);
- break;
- default:
- dev_err(&pldev->dev, "Unknown hardware, cant know what partition table to use!\n");
- goto free_master;
- break;
- }
-
- return status;
-
- free_master:
- spi_master_put(master);
- return status;
-}
-
-static int
-kp_spi_remove(struct platform_device *pldev)
-{
- struct spi_master * master = platform_get_drvdata(pldev);
- spi_unregister_master(master);
- return 0;
-}
-
-
-static struct platform_driver kp_spi_driver = {
- .driver = {
- .name = KP_DRIVER_NAME_SPI,
- },
- .probe = kp_spi_probe,
- .remove = kp_spi_remove,
-};
-
-module_platform_driver(kp_spi_driver);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:kp_spi");
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0+ */
-#ifndef __KPC_SPI_SPI_PARTS_H__
-#define __KPC_SPI_SPI_PARTS_H__
-
-static struct mtd_partition p2kr0_spi0_parts[] = {
- { .name = "SLOT_0", .size = 7798784, .offset = 0, },
- { .name = "SLOT_1", .size = 7798784, .offset = MTDPART_OFS_NXTBLK },
- { .name = "SLOT_2", .size = 7798784, .offset = MTDPART_OFS_NXTBLK },
- { .name = "SLOT_3", .size = 7798784, .offset = MTDPART_OFS_NXTBLK },
- { .name = "CS0_EXTRA", .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_NXTBLK }
-};
-static struct mtd_partition p2kr0_spi1_parts[] = {
- { .name = "SLOT_4", .size = 7798784, .offset = 0, },
- { .name = "SLOT_5", .size = 7798784, .offset = MTDPART_OFS_NXTBLK },
- { .name = "SLOT_6", .size = 7798784, .offset = MTDPART_OFS_NXTBLK },
- { .name = "SLOT_7", .size = 7798784, .offset = MTDPART_OFS_NXTBLK },
- { .name = "CS1_EXTRA", .size = MTDPART_SIZ_FULL, .offset = MTDPART_OFS_NXTBLK }
-};
-
-static struct flash_platform_data p2kr0_spi0_pdata = {
- .name = "SPI0",
- .nr_parts = ARRAY_SIZE(p2kr0_spi0_parts),
- .parts = p2kr0_spi0_parts,
-};
-static struct flash_platform_data p2kr0_spi1_pdata = {
- .name = "SPI1",
- .nr_parts = ARRAY_SIZE(p2kr0_spi1_parts),
- .parts = p2kr0_spi1_parts,
-};
-
-static struct spi_board_info p2kr0_board_info[] = {
- {
- .modalias = "n25q256a11",
- .bus_num = 1,
- .chip_select = 0,
- .mode = SPI_MODE_0,
- .platform_data = &p2kr0_spi0_pdata
- },
- {
- .modalias = "n25q256a11",
- .bus_num = 1,
- .chip_select = 1,
- .mode = SPI_MODE_0,
- .platform_data = &p2kr0_spi1_pdata
- },
-};
-
-#endif
struct sk_buff *skb),
struct sk_buff *skb)
{
- int result = 0;
+ int result;
struct hostif_hdr *hdr;
hdr = (struct hostif_hdr *)p;
unsigned int length = 0;
struct hostif_data_request *pp;
unsigned char *p;
- int result = 0;
unsigned short eth_proto;
struct ether_hdr *eth_hdr;
unsigned short keyinfo = 0;
pp->header.event = cpu_to_le16(HIF_DATA_REQ);
/* tx request */
- result = ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp) + skb_len),
- send_packet_complete, skb);
+ ret = ks_wlan_hw_tx(priv, pp, hif_align_size(sizeof(*pp) + skb_len),
+ send_packet_complete, skb);
/* MIC FAILURE REPORT check */
if (eth_proto == ETH_P_PAE &&
priv->wpa.mic_failure.stop = 1;
}
- return result;
+ return ret;
err_kfree:
kfree(pp);
tristate "MOST support"
depends on HAS_DMA && CONFIGFS_FS
default n
- ---help---
+ help
Say Y here if you want to enable MOST support.
This driver needs at least one additional component to enable the
desired access from userspace (e.g. character devices) and one that
if (len <= 0)
return NULL;
- desc = kzalloc(sizeof(struct mtk_hsdma_desc), GFP_ATOMIC);
+ desc = kzalloc(sizeof(*desc), GFP_ATOMIC);
if (!desc) {
dev_err(c->device->dev, "alloc memcpy decs error\n");
return NULL;
return -EINVAL;
hsdma = devm_kzalloc(&pdev->dev, sizeof(*hsdma), GFP_KERNEL);
- if (!hsdma) {
+ if (!hsdma)
return -EINVAL;
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
*/
static inline u32 cvmx_usb_read_csr32(struct octeon_hcd *usb, u64 address)
{
- u32 result = cvmx_read64_uint32(address ^ 4);
- return result;
+ return cvmx_read64_uint32(address ^ 4);
}
/**
static long
pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
- int retval = 0;
struct pi433_instance *instance;
struct pi433_device *device;
struct pi433_tx_cfg tx_cfg;
mutex_unlock(&device->rx_lock);
break;
default:
- retval = -EINVAL;
+ return -EINVAL;
}
- return retval;
+ return 0;
}
#ifdef CONFIG_COMPAT
switch (packet_format) {
case packet_length_var:
return rf69_set_bit(spi, REG_PACKETCONFIG1,
- MASK_PACKETCONFIG1_PAKET_FORMAT_VARIABLE);
+ MASK_PACKETCONFIG1_PACKET_FORMAT_VARIABLE);
case packet_length_fix:
return rf69_clear_bit(spi, REG_PACKETCONFIG1,
- MASK_PACKETCONFIG1_PAKET_FORMAT_VARIABLE);
+ MASK_PACKETCONFIG1_PACKET_FORMAT_VARIABLE);
default:
dev_dbg(&spi->dev, "set: illegal input param");
return -EINVAL;
#define MASK_SYNC_CONFIG_SYNC_TOLERANCE 0x07
/* RegPacketConfig1 */
-#define MASK_PACKETCONFIG1_PAKET_FORMAT_VARIABLE 0x80
+#define MASK_PACKETCONFIG1_PACKET_FORMAT_VARIABLE 0x80
#define MASK_PACKETCONFIG1_DCFREE 0x60
#define MASK_PACKETCONFIG1_CRC_ON 0x10 /* default */
#define MASK_PACKETCONFIG1_CRCAUTOCLEAR_OFF 0x08
select LIB80211
select LIB80211_CRYPT_WEP
select LIB80211_CRYPT_CCMP
- ---help---
+ help
This option adds the Realtek RTL8188EU USB device such as TP-Link TL-WN725N.
If built as a module, it will be called r8188eu.
config 88EU_AP_MODE
bool "Realtek RTL8188EU AP mode"
default y
- ---help---
+ help
This option enables Access Point mode. Unless you know that your system
will never be used as an AP, or the target system has limited memory,
"Y" should be selected.
continue;
}
break;
- } else {
- DBG_88E("%s We've try roaming but fail\n", __func__);
- rtw_indicate_disconnect(adapter);
- break;
}
+ DBG_88E("%s We've try roaming but fail\n", __func__);
+ rtw_indicate_disconnect(adapter);
+ break;
}
} else {
rtw_indicate_disconnect(adapter);
do_join_r = rtw_do_join(padapter);
if (do_join_r == _SUCCESS) {
break;
- } else {
- DBG_88E("roaming do_join return %d\n", do_join_r);
- pmlmepriv->to_roaming--;
+ }
+ DBG_88E("roaming do_join return %d\n", do_join_r);
+ pmlmepriv->to_roaming--;
- if (pmlmepriv->to_roaming > 0) {
- continue;
- } else {
- DBG_88E("%s(%d) -to roaming fail, indicate_disconnect\n", __func__, __LINE__);
- rtw_indicate_disconnect(padapter);
- break;
- }
+ if (pmlmepriv->to_roaming > 0) {
+ continue;
+ } else {
+ DBG_88E("%s(%d) -to roaming fail, indicate_disconnect\n", __func__, __LINE__);
+ rtw_indicate_disconnect(padapter);
+ break;
}
}
}
memcpy(&be_tmp, ptr, 2);
ether_type = ntohs(be_tmp);
- if ((psta != NULL) && (psta->ieee8021x_blocked)) {
+ if (psta && (psta->ieee8021x_blocked)) {
/* blocked */
/* only accept EAPOL frame */
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########%s:psta->ieee8021x_blocked==1\n", __func__));
else
*psta = rtw_get_stainfo(pstapriv, sta_addr); /* get ap_info */
- if (*psta == NULL) {
+ if (!*psta) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under %s ; drop pkt\n", __func__));
ret = _FAIL;
goto exit;
else
*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get ap_info */
- if (*psta == NULL) {
+ if (!*psta) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("ap2sta: can't get psta under STATION_MODE ; drop pkt\n"));
ret = _FAIL;
goto exit;
} else {
if (!memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && !mcast) {
*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get sta_info */
- if (*psta == NULL) {
+ if (!*psta) {
DBG_88E("issue_deauth to the ap =%pM for the reason(7)\n", (pattrib->bssid));
issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
}
*psta = rtw_get_stainfo(pstapriv, pattrib->src);
- if (*psta == NULL) {
+ if (!*psta) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under AP_MODE; drop pkt\n"));
DBG_88E("issue_deauth to sta=%pM for the reason(7)\n", (pattrib->src));
aid = GetAid(pframe);
psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
- if ((psta == NULL) || (psta->aid != aid))
+ if ((!psta) || (psta->aid != aid))
return _FAIL;
/* for rx pkt statistics */
}
}
- if ((prtnframe != NULL) && (prtnframe->attrib.privacy)) {
+ if (prtnframe && (prtnframe->attrib.privacy)) {
/* after defrag we must check tkip mic code */
if (recvframe_chkmic(padapter, prtnframe) == _FAIL) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chkmic(padapter, prtnframe)==_FAIL\n"));
union iwreq_data wrqu;
RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
- ("+rtw_report_sec_ie, authmode=%d\n", authmode));
+ ("+%s, authmode=%d\n", __func__, authmode));
buff = NULL;
if (authmode == _WPA_IE_ID_) {
RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
- ("rtw_report_sec_ie, authmode=%d\n", authmode));
+ ("%s, authmode=%d\n", __func__, authmode));
buff = rtw_malloc(IW_CUSTOM_MAX);
if (!buff)
return;
memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
- DBG_88E("+rtw_indicate_sta_assoc_event\n");
+ DBG_88E("+%s\n", __func__);
wireless_send_event(padapter->pnetdev, IWEVREGISTERED, &wrqu, NULL);
}
memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
- DBG_88E("+rtw_indicate_sta_disassoc_event\n");
+ DBG_88E("+%s\n", __func__);
wireless_send_event(padapter->pnetdev, IWEVEXPIRED, &wrqu, NULL);
}
int cmd_num;
for (cmd_num = 0; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
- if (0 == strncasecmp(cmdstr, android_wifi_cmd_str[cmd_num],
+ if (!strncasecmp(cmdstr, android_wifi_cmd_str[cmd_num],
strlen(android_wifi_cmd_str[cmd_num])))
break;
return cmd_num;
if (!priv->up) {
RT_TRACE(COMP_RATE,
- "<---- _rtl92e_dm_check_rate_adaptive(): driver is going to unload\n");
+ "<---- %s: driver is going to unload\n", __func__);
return;
}
if (!priv->up) {
RT_TRACE(COMP_RATE,
- "<---- rtl92e_dm_restore_state(): driver is going to unload\n");
+ "<---- %s: driver is going to unload\n", __func__);
return;
}
ieee80211_softmac_init(ieee);
ieee->pHTInfo = kzalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL);
- if (ieee->pHTInfo == NULL) {
+ if (!ieee->pHTInfo) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for HTInfo\n");
/* By this point in code ieee80211_networks_allocate() has been
for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) {
entry = &ieee->frag_cache[tid][i];
- if (entry->skb != NULL &&
+ if (entry->skb &&
time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
IEEE80211_DEBUG_FRAG(
"expiring fragment cache entry "
entry->skb = NULL;
}
- if (entry->skb != NULL && entry->seq == seq &&
+ if (entry->skb && entry->seq == seq &&
(entry->last_frag + 1 == frag || frag == -1) &&
memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
struct rtl_80211_hdr_4addrqos *hdr_4addrqos;
u8 tid;
- if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
+ if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) {
hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr;
tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
tid = UP2AC(tid);
if (ieee->frag_next_idx[tid] >= IEEE80211_FRAG_CACHE_LEN)
ieee->frag_next_idx[tid] = 0;
- if (entry->skb != NULL)
+ if (entry->skb)
dev_kfree_skb_any(entry->skb);
entry->first_frag_time = jiffies;
struct rtl_80211_hdr_4addrqos *hdr_4addrqos;
u8 tid;
- if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
+ if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) {
hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr;
tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
tid = UP2AC(tid);
//TO2DS and QoS
- if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
+ if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) {
hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)header;
tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
tid = UP2AC(tid);
//stats->rx_packets++;
//stats->rx_bytes += sub_skb->len;
- /* Indicat the packets to upper layer */
+ /* Indicate the packets to upper layer */
if (sub_skb) {
sub_skb->protocol = eth_type_trans(sub_skb, ieee->dev);
memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
/* just for debug purpose */
SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl));
- if ((IEEE80211_QOS_HAS_SEQ(fc))&&\
+ if ((IEEE80211_QOS_HAS_SEQ(fc)) && \
(((frameqos *)(skb->data + IEEE80211_3ADDR_LEN))->field.reserved)) {
bIsAggregateFrame = true;
}
ieee->iw_mode == IW_MODE_REPEAT) &&
!from_assoc_ap) {
switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats,
- wds != NULL)) {
+ wds)) {
case AP_RX_CONTINUE_NOT_AUTHORIZED:
case AP_RX_CONTINUE:
break;
if (stype != IEEE80211_STYPE_DATA &&
stype != IEEE80211_STYPE_DATA_CFACK &&
stype != IEEE80211_STYPE_DATA_CFPOLL &&
- stype != IEEE80211_STYPE_DATA_CFACKPOLL&&
+ stype != IEEE80211_STYPE_DATA_CFACKPOLL &&
stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4
) {
if (stype != IEEE80211_STYPE_NULLFUNC)
stats->multicast++;
}
- /* Indicat the packets to upper layer */
+ /* Indicate the packets to upper layer */
sub_skb->protocol = eth_type_trans(sub_skb, dev);
memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
sub_skb->dev = dev;
int ret = 0;
u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
- if ((info_element == NULL) || (element_param == NULL))
+ if (!info_element || !element_param)
return -1;
if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
list_for_each_entry(target, &ieee->network_list, list) {
if (is_same_network(target, network, ieee))
break;
- if ((oldest == NULL) ||
+ if (!oldest ||
(target->last_scanned < oldest->last_scanned))
oldest = target;
}
// printk("====>2 network->ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network->ssid, network->flags, target->ssid, target->flags);
if(((network->flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \
&& (((network->ssid_len > 0) && (strncmp(target->ssid, network->ssid, network->ssid_len)))\
- ||((ieee->current_network.ssid_len == network->ssid_len)&&(strncmp(ieee->current_network.ssid, network->ssid, network->ssid_len) == 0)&&(ieee->state == IEEE80211_NOLINK))))
+ ||((ieee->current_network.ssid_len == network->ssid_len) && (strncmp(ieee->current_network.ssid, network->ssid, network->ssid_len) == 0) && (ieee->state == IEEE80211_NOLINK))))
renew = 1;
//YJ,add,080819,for hidden ap,end
}
spin_unlock_irqrestore(&ieee->lock, flags);
- if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, network, ieee)&&\
+ if (is_beacon(beacon->header.frame_ctl) && is_same_network(&ieee->current_network, network, ieee) && \
(ieee->state == IEEE80211_LINKED)) {
- if (ieee->handle_beacon != NULL) {
+ if (ieee->handle_beacon)
ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network);
- }
}
out:
u8 *act = ieee80211_get_payload(header);
u8 tmp = 0;
// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
- if (act == NULL) {
+ if (!act) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
return;
}
memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
}
- if (ieee->handle_assoc_response != NULL)
+ if (ieee->handle_assoc_response)
ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame *)header, network);
}
ieee80211_associate_complete(ieee);
{
u8 *buf;
- if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
- (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
+ if (param->u.wpa_ie.len > MAX_WPA_IE_LEN)
return -EINVAL;
if (param->u.wpa_ie.len) {
buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
GFP_KERNEL);
- if (buf == NULL)
+ if (!buf)
return -ENOMEM;
kfree(ieee->wpa_ie);
goto done;
}
- if (*crypt == NULL || (*crypt)->ops != ops) {
+ if (!*crypt || (*crypt)->ops != ops) {
struct ieee80211_crypt_data *new_crypt;
ieee80211_crypt_delayed_deinit(ieee, crypt);
new_crypt->priv =
new_crypt->ops->init(param->u.crypt.idx);
- if (new_crypt->priv == NULL) {
+ if (!new_crypt->priv) {
kfree(new_crypt);
param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
ret = -EINVAL;
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- if (wrqu->rts.disabled || !wrqu->rts.fixed)
+ if (wrqu->rts.disabled || !wrqu->rts.fixed) {
ieee->rts = DEFAULT_RTS_THRESHOLD;
- else {
+ } else {
if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
wrqu->rts.value > MAX_RTS_THRESHOLD)
return -EINVAL;
struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
int res;
- if (!(crypt && crypt->ops))
- {
+ if (!(crypt && crypt->ops)) {
printk("=========>%s(), crypt is null\n", __func__);
return -1;
}
if (!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter))
return;
#endif
- if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
- {
+ if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) {
return;
}
- if (pHTInfo->bCurrentAMPDUEnable)
- {
- if (!GetTs(ieee, (struct ts_common_info **)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true))
- {
+ if (pHTInfo->bCurrentAMPDUEnable) {
+ if (!GetTs(ieee, (struct ts_common_info **)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true)) {
printk("===>can't get TS\n");
return;
}
- if (!pTxTs->tx_admitted_ba_record.valid)
- {
+ if (!pTxTs->tx_admitted_ba_record.valid) {
TsStartAddBaProcess(ieee, pTxTs);
goto FORCED_AGG_SETTING;
- }
- else if (!pTxTs->using_ba)
- {
+ } else if (!pTxTs->using_ba) {
if (SN_LESS(pTxTs->tx_admitted_ba_record.start_seq_ctrl.field.seq_num, (pTxTs->tx_cur_seq + 1) % 4096))
pTxTs->using_ba = true;
else
goto FORCED_AGG_SETTING;
}
- if (ieee->iw_mode == IW_MODE_INFRA)
- {
+ if (ieee->iw_mode == IW_MODE_INFRA) {
tcb_desc->bAMPDUEnable = true;
tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
struct cb_desc *tcb_desc)
{
tcb_desc->bUseShortPreamble = false;
- if (tcb_desc->data_rate == 2)
- {//// 1M can only use Long Preamble. 11B spec
+ if (tcb_desc->data_rate == 2) {//// 1M can only use Long Preamble. 11B spec
return;
- }
- else if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
- {
+ } else if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
tcb_desc->bUseShortPreamble = true;
}
return;
if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
return;
- if (pHTInfo->bForcedShortGI)
- {
+ if (pHTInfo->bForcedShortGI) {
tcb_desc->bUseShortGI = true;
return;
}
struct cb_desc *tcb_desc)
{
#ifdef TO_DO_LIST
- if(!IsDataFrame(pFrame))
- {
+ if (!IsDataFrame(pFrame)) {
pTcb->bTxDisableRateFallBack = true;
pTcb->bTxUseDriverAssingedRate = true;
pTcb->RATRIndex = 7;
return;
}
- if(pMgntInfo->ForcedDataRate!= 0)
- {
+ if (pMgntInfo->ForcedDataRate!= 0) {
pTcb->bTxDisableRateFallBack = true;
pTcb->bTxUseDriverAssingedRate = true;
return;
}
#endif
- if(ieee->bTxDisableRateFallBack)
+ if (ieee->bTxDisableRateFallBack)
tcb_desc->bTxDisableRateFallBack = true;
- if(ieee->bTxUseDriverAssingedRate)
+ if (ieee->bTxUseDriverAssingedRate)
tcb_desc->bTxUseDriverAssingedRate = true;
- if(!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate)
+ if (!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate)
{
if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
tcb_desc->RATRIndex = 0;
}
- if(likely(ieee->raw_tx == 0)){
+ if (likely(ieee->raw_tx == 0)) {
if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
printk(KERN_WARNING "%s: skb too small (%d).\n",
ieee->dev->name, skb->len);
if (is_multicast_ether_addr(header.addr1)) {
frag_size = MAX_FRAG_THRESHOLD;
qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
- }
- else {
+ } else {
frag_size = ieee->fts;//default:392
qos_ctl = 0;
}
//if (ieee->current_network.QoS_Enable)
- if(qos_actived)
- {
+ if (qos_actived) {
hdr_len = IEEE80211_3ADDR_LEN + 2;
skb->priority = ieee80211_classify(skb, &ieee->current_network);
txb->payload_size = __cpu_to_le16(bytes);
//if (ieee->current_network.QoS_Enable)
- if(qos_actived)
- {
+ if (qos_actived)
txb->queue_index = UP2AC(skb->priority);
- } else {
+ else
txb->queue_index = WME_AC_BK;
- }
list_for_each_entry(network, &ieee->network_list, list) {
i++;
- if((stop-ev)<200)
- {
+ if((stop-ev)<200) {
err = -E2BIG;
break;
}
/* Check all the keys to see if any are still configured,
* and if no key index was provided, de-init them all */
for (i = 0; i < WEP_KEYS; i++) {
- if (ieee->crypt[i] != NULL) {
+ if (ieee->crypt[i]) {
if (key_provided)
break;
ieee80211_crypt_delayed_deinit(
sec.enabled = 1;
sec.flags |= SEC_ENABLED;
- if (*crypt != NULL && (*crypt)->ops != NULL &&
+ if (*crypt && (*crypt)->ops &&
strcmp((*crypt)->ops->name, "WEP") != 0) {
/* changing to use WEP; deinit previously used algorithm
* on this key */
ieee80211_crypt_delayed_deinit(ieee, crypt);
}
- if (*crypt == NULL) {
+ if (!*crypt) {
struct ieee80211_crypt_data *new_crypt;
/* take WEP into use */
crypt = ieee->crypt[key];
erq->flags = key + 1;
- if (crypt == NULL || crypt->ops == NULL) {
+ if (!crypt || !crypt->ops) {
erq->length = 0;
erq->flags |= IW_ENCODE_DISABLED;
return 0;
for (i = 0; i < WEP_KEYS; i++)
- if (ieee->crypt[i] != NULL)
+ if (ieee->crypt[i])
break;
goto done;
}
- if (*crypt == NULL || (*crypt)->ops != ops) {
+ if (!*crypt || (*crypt)->ops != ops) {
struct ieee80211_crypt_data *new_crypt;
ieee80211_crypt_delayed_deinit(ieee, crypt);
new_crypt->ops = ops;
if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
new_crypt->priv = new_crypt->ops->init(idx);
- if (new_crypt->priv == NULL) {
+ if (!new_crypt->priv) {
kfree(new_crypt);
ret = -EINVAL;
goto done;
encoding->flags = idx + 1;
memset(ext, 0, sizeof(*ext));
- if (crypt == NULL || crypt->ops == NULL ) {
+ if (!crypt || !crypt->ops) {
ext->alg = IW_ENCODE_ALG_NONE;
ext->key_len = 0;
encoding->flags |= IW_ENCODE_DISABLED;
} else if (data->value & IW_AUTH_ALG_LEAP) {
ieee->open_wep = 1;
ieee->auth_mode = 2;
- }
- else
+ } else
return -EINVAL;
break;
{
u8 *buf;
- if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
- {
+ if (len>MAX_WPA_IE_LEN || (len && !ie)) {
// printk("return error out, len:%d\n", len);
return -EINVAL;
}
- if (len)
- {
- if (len != ie[1]+2)
- {
+ if (len) {
+ if (len != ie[1]+2) {
printk("len:%zu, ie:%d\n", len, ie[1]);
return -EINVAL;
}
buf = kmemdup(ie, len, GFP_KERNEL);
- if (buf == NULL)
+ if (!buf)
return -ENOMEM;
kfree(ieee->wpa_ie);
ieee->wpa_ie = buf;
ieee->wpa_ie_len = len;
- }
- else{
+ } else {
kfree(ieee->wpa_ie);
ieee->wpa_ie = NULL;
ieee->wpa_ie_len = 0;
if (SN_EQUAL(pReorderEntry->SeqNum, pRxTs->rx_indicate_seq))
pRxTs->rx_indicate_seq = (pRxTs->rx_indicate_seq + 1) % 4096;
- IEEE80211_DEBUG(IEEE80211_DL_REORDER, "RxPktPendingTimeout(): IndicateSeq: %d\n", pReorderEntry->SeqNum);
+ IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s: IndicateSeq: %d\n", __func__, pReorderEntry->SeqNum);
ieee->stats_IndicateArray[index] = pReorderEntry->prxb;
index++;
struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[num]);
TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false);
- IEEE80211_DEBUG(IEEE80211_DL_BA, "TsAddBaProcess(): ADDBA Req is started!! \n");
+ IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: ADDBA Req is started!! \n", __func__);
}
{
struct ts_common_info *pTS, *pTmpTS;
- printk("===========>RemovePeerTS,%pM\n", Addr);
+ printk("===========>%s,%pM\n", __func__, Addr);
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, list) {
if (memcmp(pTS->addr, Addr, 6) == 0) {
RemoveTsEntry(ieee, pTS, TX_DIR);
if (!pTxTS->add_ba_req_in_progress) {
pTxTS->add_ba_req_in_progress = true;
if (pTxTS->add_ba_req_delayed) {
- IEEE80211_DEBUG(IEEE80211_DL_BA, "TsStartAddBaProcess(): Delayed Start ADDBA after 60 sec!!\n");
+ IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: Delayed Start ADDBA after 60 sec!!\n", __func__);
mod_timer(&pTxTS->ts_add_ba_timer,
jiffies + msecs_to_jiffies(TS_ADDBA_DELAY));
} else {
- IEEE80211_DEBUG(IEEE80211_DL_BA, "TsStartAddBaProcess(): Immediately Start ADDBA now!!\n");
+ IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: Immediately Start ADDBA now!!\n", __func__);
mod_timer(&pTxTS->ts_add_ba_timer, jiffies+10); //set 10 ticks
}
} else {
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
#endif
u8 blnSetTxDescOffset;
- sint bmcst = IS_MCAST(pattrib->ra);
+ bool bmcst = is_multicast_ether_addr(pattrib->ra);
struct ht_priv *phtpriv = &pmlmepriv->htpriv;
struct tx_desc txdesc_mp;
struct iw_request_info *info,
union iwreq_data *wrqu, char *keybuf)
{
- uint key, ret = 0;
+ uint key;
struct _adapter *padapter = netdev_priv(dev);
struct iw_point *erq = &(wrqu->encoding);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
erq->flags |= IW_ENCODE_DISABLED;
break;
}
- return ret;
+ return 0;
}
static int r8711_wx_get_power(struct net_device *dev,
u32 r8712_GetPhyRxPktReceived(struct _adapter *pAdapter)
{
- u32 OFDM_cnt = 0, CCK_cnt = 0, HT_cnt = 0;
+ u32 OFDM_cnt = GetPhyRxPktCounts(pAdapter, OFDM_MPDU_OK_BIT);
+ u32 CCK_cnt = GetPhyRxPktCounts(pAdapter, CCK_MPDU_OK_BIT);
+ u32 HT_cnt = GetPhyRxPktCounts(pAdapter, HT_MPDU_OK_BIT);
- OFDM_cnt = GetPhyRxPktCounts(pAdapter, OFDM_MPDU_OK_BIT);
- CCK_cnt = GetPhyRxPktCounts(pAdapter, CCK_MPDU_OK_BIT);
- HT_cnt = GetPhyRxPktCounts(pAdapter, HT_MPDU_OK_BIT);
return OFDM_cnt + CCK_cnt + HT_cnt;
}
u32 r8712_GetPhyRxPktCRC32Error(struct _adapter *pAdapter)
{
- u32 OFDM_cnt = 0, CCK_cnt = 0, HT_cnt = 0;
+ u32 OFDM_cnt = GetPhyRxPktCounts(pAdapter, OFDM_MPDU_FAIL_BIT);
+ u32 CCK_cnt = GetPhyRxPktCounts(pAdapter, CCK_MPDU_FAIL_BIT);
+ u32 HT_cnt = GetPhyRxPktCounts(pAdapter, HT_MPDU_FAIL_BIT);
- OFDM_cnt = GetPhyRxPktCounts(pAdapter, OFDM_MPDU_FAIL_BIT);
- CCK_cnt = GetPhyRxPktCounts(pAdapter, CCK_MPDU_FAIL_BIT);
- HT_cnt = GetPhyRxPktCounts(pAdapter, HT_MPDU_FAIL_BIT);
return OFDM_cnt + CCK_cnt + HT_cnt;
}
if (prxattrib->encrypt == _TKIP_) {
/* calculate mic code */
if (stainfo != NULL) {
- if (IS_MCAST(prxattrib->ra)) {
+ if (is_multicast_ether_addr(prxattrib->ra)) {
iv = precvframe->u.hdr.rx_data +
prxattrib->hdrlen;
idx = iv[3];
if (bmic_err) {
if (prxattrib->bdecrypted)
r8712_handle_tkip_mic_err(adapter,
- (u8)IS_MCAST(prxattrib->ra));
+ (u8)is_multicast_ether_addr(prxattrib->ra));
res = _FAIL;
} else {
/* mic checked ok */
if (!psecuritypriv->bcheck_grpkey &&
- IS_MCAST(prxattrib->ra))
+ is_multicast_ether_addr(prxattrib->ra))
psecuritypriv->bcheck_grpkey = true;
}
recvframe_pull_tail(precvframe, 8);
u8 *mybssid = get_bssid(pmlmepriv);
u8 *myhwaddr = myid(&adapter->eeprompriv);
u8 *sta_addr = NULL;
- sint bmcast = IS_MCAST(pattrib->dst);
+ bool bmcast = is_multicast_ether_addr(pattrib->dst);
if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
/* For AP mode, if DA == MCAST, then BSSID should
* be also MCAST
*/
- if (!IS_MCAST(pattrib->bssid))
+ if (!is_multicast_ether_addr(pattrib->bssid))
return _FAIL;
} else { /* not mc-frame */
/* For AP mode, if DA is non-MCAST, then it must be
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
u8 *mybssid = get_bssid(pmlmepriv);
u8 *myhwaddr = myid(&adapter->eeprompriv);
- sint bmcast = IS_MCAST(pattrib->dst);
+ bool bmcast = is_multicast_ether_addr(pattrib->dst);
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
check_fwstate(pmlmepriv, _FW_LINKED)) {
if (pattrib->privacy) {
GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt,
- IS_MCAST(pattrib->ra));
+ is_multicast_ether_addr(pattrib->ra));
SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len,
pattrib->encrypt);
} else {
length = ((union recv_frame *)precvframe)->
u.hdr.len - prxattrib->hdrlen -
prxattrib->iv_len;
- if (IS_MCAST(prxattrib->ra)) {
+ if (is_multicast_ether_addr(prxattrib->ra)) {
idx = iv[3];
prwskey = &psecuritypriv->XGrpKey[
((idx >> 6) & 0x3) - 1].skey[0];
stainfo = r8712_get_stainfo(&padapter->stapriv,
&prxattrib->ta[0]);
if (stainfo != NULL) {
- if (IS_MCAST(prxattrib->ra)) {
+ if (is_multicast_ether_addr(prxattrib->ra)) {
iv = pframe + prxattrib->hdrlen;
idx = iv[3];
prwskey = &psecuritypriv->XGrpKey[
struct tx_cmd txdesc;
- sint bmcast;
+ bool bmcast;
struct sta_priv *pstapriv = &padapter->stapriv;
struct security_priv *psecuritypriv = &padapter->securitypriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
}
}
}
- bmcast = IS_MCAST(pattrib->ra);
+ bmcast = is_multicast_ether_addr(pattrib->ra);
/* get sta_info*/
if (bmcast) {
psta = r8712_get_bcmc_stainfo(padapter);
struct security_priv *psecuritypriv = &padapter->securitypriv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
- sint bmcst = IS_MCAST(pattrib->ra);
+ bool bmcst = is_multicast_ether_addr(pattrib->ra);
if (pattrib->psta)
stainfo = pattrib->psta;
/* Update Seq Num will be handled by f/w */
{
struct sta_info *psta;
- sint bmcst = IS_MCAST(pattrib->ra);
+ bool bmcst = is_multicast_ether_addr(pattrib->ra);
if (pattrib->psta) {
psta = pattrib->psta;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
u8 *pbuf_start;
- sint bmcst = IS_MCAST(pattrib->ra);
+ bool bmcst = is_multicast_ether_addr(pattrib->ra);
if (pattrib->psta == NULL)
return _FAIL;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct sta_priv *pstapriv = &padapter->stapriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- sint bmcst = IS_MCAST(pattrib->ra);
+ bool bmcst = is_multicast_ether_addr(pattrib->ra);
if (pattrib->psta) {
psta = pattrib->psta;
#define GetAddr4Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 24))
-
-
-static inline int IS_MCAST(unsigned char *da)
-{
- if ((*da) & 0x01)
- return true;
- else
- return false;
-}
-
-
static inline unsigned char *get_da(unsigned char *pframe)
{
unsigned char *da;
depends on m
select WIRELESS_EXT
select WEXT_PRIV
- ---help---
+ help
This option enables support for RTL8723BS SDIO drivers, such as
the wifi found on the 1st gen Intel Compute Stick, the CHIP
and many other Intel Atom and ARM based devices.
void associated_clients_update(struct adapter *padapter, u8 updated)
{
- /* update associcated stations cap. */
+ /* update associated stations cap. */
if (updated) {
struct list_head *phead, *plist;
struct sta_info *psta = NULL;
update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
}
- /* update associcated stations cap. */
+ /* update associated stations cap. */
associated_clients_update(padapter, beacon_updated);
DBG_871X("%s, updated =%d\n", __func__, beacon_updated);
update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
}
- /* update associcated stations cap. */
+ /* update associated stations cap. */
/* associated_clients_update(padapter, beacon_updated); //move it to avoid deadlock */
DBG_871X("%s, updated =%d\n", __func__, beacon_updated);
if (!psta)
return beacon_updated;
- if (active == true) {
+ if (active) {
/* tear down Rx AMPDU */
send_delba(padapter, 0, psta->hwaddr);/* recipient */
return beacon_updated;
}
-int rtw_sta_flush(struct adapter *padapter)
+void rtw_sta_flush(struct adapter *padapter)
{
struct list_head *phead, *plist;
- int ret = 0;
struct sta_info *psta = NULL;
struct sta_priv *pstapriv = &padapter->stapriv;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
- return ret;
+ return;
spin_lock_bh(&pstapriv->asoc_list_lock);
phead = &pstapriv->asoc_list;
issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
associated_clients_update(padapter, true);
-
- return ret;
}
/* called > TSR LEVEL for USB or SDIO Interface*/
pstapriv->tim_bitmap &= ~BIT(0);
pstapriv->sta_dz_bitmap &= ~BIT(0);
- if (update_tim == true)
+ if (update_tim)
update_beacon(padapter, _TIM_IE_, NULL, true);
} else {/* re check again */
rtw_chk_hi_queue_cmd(padapter);
if (!bssid || rtw_validate_bssid(bssid) == false)
bssid_valid = false;
- if (ssid_valid == false && bssid_valid == false) {
+ if (!ssid_valid && !bssid_valid) {
DBG_871X(FUNC_ADPT_FMT" ssid:%p, ssid_valid:%d, bssid:%p, bssid_valid:%d\n",
FUNC_ADPT_ARG(padapter), ssid, ssid_valid, bssid, bssid_valid);
status = _FAIL;
roam_target = pmlmepriv->roam_network;
}
- if (roam == true) {
+ if (roam) {
if (rtw_to_roam(adapter) > 0)
rtw_dec_to_roam(adapter); /* this stadel_event is caused by roaming, decrease to_roam */
else if (rtw_to_roam(adapter) == 0)
#include <rtw_wifi_regd.h>
#include <linux/kernel.h>
-
static struct mlme_handler mlme_sta_tbl[] = {
{WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq},
{WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp},
{RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &DoReserved},
};
-
static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
/**************************************************
static void init_mlme_ext_priv_value(struct adapter *padapter)
{
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
atomic_set(&pmlmeext->event_seq, 0);
pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
struct p2p_reg_class *reg = NULL;
for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
- if (!has_channel(channel_set, chanset_size, ch)) {
+ if (!has_channel(channel_set, chanset_size, ch))
continue;
- }
if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc))
continue;
((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
continue;
- if (reg == NULL) {
+ if (!reg) {
reg = &channel_list->reg_class[cla];
cla++;
reg->reg_class = o->op_class;
int res = _SUCCESS;
struct registry_priv *pregistrypriv = &padapter->registrypriv;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
pmlmeext->padapter = padapter;
unsigned char *p;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur = &pmlmeinfo->network;
u8 *pframe = precv_frame->u.hdr.rx_data;
uint len = precv_frame->u.hdr.len;
u8 is_valid_p2p_probereq = false;
/* allocate a new one */
DBG_871X("going to alloc stainfo for rc ="MAC_FMT"\n", MAC_ARG(get_sa(pframe)));
psta = rtw_alloc_stainfo(pstapriv, get_sa(pframe));
- if (psta == NULL) {
+ if (!psta) {
/* TODO: */
DBG_871X(" Exceed the upper limit of supported clients...\n");
return _SUCCESS;
}
pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
- if (pstat == NULL) {
+ if (!pstat) {
status = _RSON_CLS2_;
goto asoc_class2_error;
}
goto OnAssocReqFail;
}
-
/* now we should check all the fields... */
/* checking SSID */
p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
status = _STATS_FAILURE_;
}
- if (_STATS_SUCCESSFUL_ != status)
+ if (status != _STATS_SUCCESSFUL_)
goto OnAssocReqFail;
/* check if the supported rate is ok */
wpa_ie_len = 0;
}
- if (_STATS_SUCCESSFUL_ != status)
+ if (status != _STATS_SUCCESSFUL_)
goto OnAssocReqFail;
pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
- if (wpa_ie == NULL) {
+ if (!wpa_ie) {
if (elems.wps_ie) {
DBG_871X("STA included WPS IE in "
"(Re)Association Request - assume WPS is "
addr = GetAddr2Ptr(pframe);
psta = rtw_get_stainfo(pstapriv, addr);
- if (psta == NULL)
+ if (!psta)
return _SUCCESS;
frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
category = frame_body[0];
if (category == RTW_WLAN_CATEGORY_BACK) {/* representing Block Ack */
- if (!pmlmeinfo->HT_enable) {
+ if (!pmlmeinfo->HT_enable)
return _SUCCESS;
- }
action = frame_body[1];
DBG_871X("%s, action =%d\n", __func__, action);
pxmitpriv->ack_tx = true;
pxmitpriv->seq_no = seq_no++;
pmgntframe->ack_report = 1;
- if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
+ if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
- }
pxmitpriv->ack_tx = false;
mutex_unlock(&pxmitpriv->ack_tx_mutex);
/* DBG_871X("%s\n", __func__); */
pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL) {
+ if (!pmgntframe) {
DBG_871X("%s, alloc mgnt frame fail\n", __func__);
return;
}
RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+issue_probereq\n"));
pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
+ if (!pmgntframe)
goto exit;
/* update attribute */
}
-
if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &(pattrib->pktlen));
}
pattrib = &pmgntframe->attrib;
update_mgntframe_attrib(padapter, pattrib);
-
memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
DBG_871X("%s, category =%d, action =%d, status =%d\n", __func__, category, action, status);
pmgntframe = alloc_mgtxmitframe(pxmitpriv);
- if (pmgntframe == NULL)
+ if (!pmgntframe)
return;
/* update attribute */
pcmdpriv = &padapter->cmdpriv;
pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd_obj == NULL)
+ if (!pcmd_obj)
return;
cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
pevtcmd = rtw_zmalloc(cmdsz);
- if (pevtcmd == NULL) {
+ if (!pevtcmd) {
kfree(pcmd_obj);
return;
}
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd_obj == NULL)
+ if (!pcmd_obj)
return;
cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
pevtcmd = rtw_zmalloc(cmdsz);
- if (pevtcmd == NULL) {
+ if (!pevtcmd) {
kfree(pcmd_obj);
return;
}
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd_obj == NULL)
+ if (!pcmd_obj)
return;
cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
pevtcmd = rtw_zmalloc(cmdsz);
- if (pevtcmd == NULL) {
+ if (!pevtcmd) {
kfree(pcmd_obj);
return;
}
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
- if (pcmd_obj == NULL)
+ if (!pcmd_obj)
return;
cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header));
pevtcmd = rtw_zmalloc(cmdsz);
- if (pevtcmd == NULL) {
+ if (!pevtcmd) {
kfree(pcmd_obj);
return;
}
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
- if (pparm->mode < 4) {
+ if (pparm->mode < 4)
pmlmeinfo->auth_algo = pparm->mode;
- }
return H2C_SUCCESS;
}
*offset = cur_ch_offset;
}
- return connect_allow == true ? _SUCCESS : _FAIL;
+ return connect_allow ? _SUCCESS : _FAIL;
}
/* Find union about ch, bw, ch_offset of all linked/linking interfaces */
if (pwrpriv->ips_mode_req == IPS_NONE)
goto exit;
- if (rtw_pwr_unassociated_idle(padapter) == false)
+ if (!rtw_pwr_unassociated_idle(padapter))
goto exit;
if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4) == 0)) {
precvpriv->pallocated_frame_buf = vzalloc(NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
- if (precvpriv->pallocated_frame_buf == NULL) {
+ if (!precvpriv->pallocated_frame_buf) {
res = _FAIL;
goto exit;
}
list_del_init(&precvframe->u.hdr.list);
padapter = precvframe->u.hdr.adapter;
- if (padapter != NULL) {
+ if (padapter) {
precvpriv = &padapter->recvpriv;
if (pfree_recv_queue == &precvpriv->free_recv_queue)
precvpriv->free_recvframe_cnt--;
list_add_tail(&(precvframe->u.hdr.list), get_list_head(pfree_recv_queue));
- if (padapter != NULL) {
+ if (padapter) {
if (pfree_recv_queue == &precvpriv->free_recv_queue)
precvpriv->free_recvframe_cnt++;
}
list_add_tail(&(precvframe->u.hdr.list), get_list_head(queue));
- if (padapter != NULL)
+ if (padapter)
if (queue == &precvpriv->free_recv_queue)
precvpriv->free_recvframe_cnt++;
prxattrib->ra[0], prxattrib->ra[1], prxattrib->ra[2], prxattrib->ra[3], prxattrib->ra[4], prxattrib->ra[5]));
/* calculate mic code */
- if (stainfo != NULL) {
+ if (stainfo) {
if (IS_MCAST(prxattrib->ra)) {
/* mickey =&psecuritypriv->dot118021XGrprxmickey.skey[0]; */
/* iv = precvframe->u.hdr.rx_data+prxattrib->hdrlen; */
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:adapter->securitypriv.dot11AuthAlgrthm =%d\n", adapter->securitypriv.dot11AuthAlgrthm));
if (auth_alg == 2) {
- if ((psta != NULL) && (psta->ieee8021x_blocked)) {
+ if ((psta) && (psta->ieee8021x_blocked)) {
__be16 be_tmp;
/* blocked */
else
*psta = rtw_get_stainfo(pstapriv, sta_addr); /* get ap_info */
- if (*psta == NULL) {
+ if (!*psta) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under sta2sta_data_frame ; drop pkt\n"));
ret = _FAIL;
goto exit;
else
*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get ap_info */
- if (*psta == NULL) {
+ if (!*psta) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("ap2sta: can't get psta under STATION_MODE ; drop pkt\n"));
#ifdef DBG_RX_DROP_FRAME
DBG_871X("DBG_RX_DROP_FRAME %s can't get psta under STATION_MODE ; drop pkt\n", __func__);
*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get sta_info */
- if (*psta == NULL) {
+ if (!*psta) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under MP_MODE ; drop pkt\n"));
#ifdef DBG_RX_DROP_FRAME
DBG_871X("DBG_RX_DROP_FRAME %s can't get psta under WIFI_MP_STATE ; drop pkt\n", __func__);
} else {
if (!memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && (!bmcast)) {
*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get sta_info */
- if (*psta == NULL) {
+ if (!*psta) {
/* for AP multicast issue , modify by yiwei */
static unsigned long send_issue_deauth_time;
}
*psta = rtw_get_stainfo(pstapriv, pattrib->src);
- if (*psta == NULL) {
+ if (!*psta) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under AP_MODE; drop pkt\n"));
DBG_871X("issue_deauth to sta =" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->src));
return _FAIL;
psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
- if (psta == NULL)
+ if (!psta)
return _FAIL;
/* for rx pkt statistics */
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("+validate_recv_mgnt_frame\n"));
precv_frame = recvframe_chk_defrag(padapter, precv_frame);
- if (precv_frame == NULL) {
+ if (!precv_frame) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("%s: fragment packet\n", __func__));
return _SUCCESS;
}
psa = get_sa(ptr);
pbssid = get_hdr_bssid(ptr);
- if (pbssid == NULL) {
+ if (!pbssid) {
#ifdef DBG_RX_DROP_FRAME
DBG_871X("DBG_RX_DROP_FRAME %s pbssid == NULL\n", __func__);
#endif
}
- if (psta == NULL) {
+ if (!psta) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" after to_fr_ds_chk; psta == NULL\n"));
#ifdef DBG_RX_DROP_FRAME
DBG_871X("DBG_RX_DROP_FRAME %s psta == NULL\n", __func__);
/* actual management data frame body */
data_len = pattrib->pkt_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len;
mgmt_DATA = rtw_zmalloc(data_len);
- if (mgmt_DATA == NULL) {
+ if (!mgmt_DATA) {
DBG_871X("%s mgmt allocate fail !!!!!!!!!\n", __func__);
goto validate_80211w_fail;
}
u8 *psnap_type;
struct ieee80211_snap_hdr *psnap;
__be16 be_tmp;
- sint ret = _SUCCESS;
struct adapter *adapter = precvframe->u.hdr.adapter;
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
u8 *ptr = get_recvframe_data(precvframe) ; /* point to frame_ctrl field */
memcpy(ptr+12, &be_tmp, 2);
}
- return ret;
+ return _SUCCESS;
}
/* perform defrag */
psta_addr = pfhdr->attrib.ta;
psta = rtw_get_stainfo(pstapriv, psta_addr);
- if (psta == NULL) {
+ if (!psta) {
u8 type = GetFrameType(pfhdr->rx_data);
if (type != WIFI_DATA_TYPE) {
psta = rtw_get_bcmc_stainfo(padapter);
if (ismfrag == 1) {
/* 0~(n-1) fragment frame */
/* enqueue to defraf_g */
- if (pdefrag_q != NULL) {
+ if (pdefrag_q) {
if (fragnum == 0)
/* the first fragment */
if (!list_empty(&pdefrag_q->queue))
if ((ismfrag == 0) && (fragnum != 0)) {
/* the last fragment frame */
/* enqueue the last fragment */
- if (pdefrag_q != NULL) {
+ if (pdefrag_q) {
/* spin_lock(&pdefrag_q->lock); */
phead = get_list_head(pdefrag_q);
list_add_tail(&pfhdr->list, phead);
}
- if ((prtnframe != NULL) && (prtnframe->u.hdr.attrib.privacy)) {
+ if ((prtnframe) && (prtnframe->u.hdr.attrib.privacy)) {
/* after defrag we must check tkip mic code */
if (recvframe_chkmic(padapter, prtnframe) == _FAIL) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chkmic(padapter, prtnframe) == _FAIL\n"));
_pkt *sub_pkt, *subframes[MAX_SUBFRAME_COUNT];
struct recv_priv *precvpriv = &padapter->recvpriv;
struct __queue *pfree_recv_queue = &(precvpriv->free_recv_queue);
- int ret = _SUCCESS;
nr_subframes = 0;
}
sub_pkt = rtw_os_alloc_msdu_pkt(prframe, nSubframe_Length, pdata);
- if (sub_pkt == NULL) {
+ if (!sub_pkt) {
DBG_871X("%s(): allocate sub packet fail !!!\n", __func__);
break;
}
prframe->u.hdr.len = 0;
rtw_free_recvframe(prframe, pfree_recv_queue);/* free this recv_frame */
- return ret;
+ return _SUCCESS;
}
int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num);
DBG_COUNTER(padapter->rx_logs.core_rx_post);
prframe = decryptor(padapter, prframe);
- if (prframe == NULL) {
+ if (!prframe) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("decryptor: drop pkt\n"));
#ifdef DBG_RX_DROP_FRAME
DBG_871X("DBG_RX_DROP_FRAME %s decryptor: drop pkt\n", __func__);
}
prframe = recvframe_chk_defrag(padapter, prframe);
- if (prframe == NULL) {
+ if (!prframe) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chk_defrag: drop pkt\n"));
#ifdef DBG_RX_DROP_FRAME
DBG_871X("DBG_RX_DROP_FRAME %s recvframe_chk_defrag: drop pkt\n", __func__);
}
prframe = portctrl(padapter, prframe);
- if (prframe == NULL) {
+ if (!prframe) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("portctrl: drop pkt\n"));
#ifdef DBG_RX_DROP_FRAME
DBG_871X("DBG_RX_DROP_FRAME %s portctrl: drop pkt\n", __func__);
i = _rtw_camid_search(adapter, addr, kid);
if (i >= 0) {
/* Fix issue that pairwise and group key have same key id. Pairwise key first, group key can overwirte group only(ex: rekey) */
- if (sta || _rtw_camid_is_gk(adapter, i) == true)
+ if (sta || _rtw_camid_is_gk(adapter, i))
cam_id = i;
else
DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" group key id:%u the same key id as pairwise key\n"
pxmitpriv->pallocated_frame_buf = vzalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
- if (pxmitpriv->pallocated_frame_buf == NULL) {
+ if (!pxmitpriv->pallocated_frame_buf) {
pxmitpriv->pxmit_frame_buf = NULL;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_frame fail!\n"));
res = _FAIL;
pxmitpriv->pallocated_xmitbuf = vzalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4);
- if (pxmitpriv->pallocated_xmitbuf == NULL) {
+ if (!pxmitpriv->pallocated_xmitbuf) {
RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_buf fail!\n"));
res = _FAIL;
goto exit;
pxmitpriv->xframe_ext_alloc_addr = vzalloc(NR_XMIT_EXTBUFF * sizeof(struct xmit_frame) + 4);
- if (pxmitpriv->xframe_ext_alloc_addr == NULL) {
+ if (!pxmitpriv->xframe_ext_alloc_addr) {
pxmitpriv->xframe_ext = NULL;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xframe_ext fail!\n"));
res = _FAIL;
pxmitpriv->pallocated_xmit_extbuf = vzalloc(NR_XMIT_EXTBUFF * sizeof(struct xmit_buf) + 4);
- if (pxmitpriv->pallocated_xmit_extbuf == NULL) {
+ if (!pxmitpriv->pallocated_xmit_extbuf) {
RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_extbuf fail!\n"));
res = _FAIL;
goto exit;
rtw_hal_free_xmit_priv(padapter);
- if (pxmitpriv->pxmit_frame_buf == NULL)
+ if (!pxmitpriv->pxmit_frame_buf)
return;
for (i = 0; i < NR_XMITFRAME; i++) {
for (i = 0; i < CMDBUF_MAX; i++) {
pxmitbuf = &pxmitpriv->pcmd_xmitbuf[i];
- if (pxmitbuf != NULL)
+ if (pxmitbuf)
rtw_os_xmit_resource_free(padapter, pxmitbuf, MAX_CMDBUF_SZ+XMITBUF_ALIGN_SZ, true);
}
psta = rtw_get_bcmc_stainfo(padapter);
} else {
psta = rtw_get_stainfo(pstapriv, pattrib->ra);
- if (psta == NULL) { /* if we cannot get psta => drop the pkt */
+ if (!psta) { /* if we cannot get psta => drop the pkt */
DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_ucast_sta);
RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("\nupdate_attrib => get sta_info fail, ra:" MAC_FMT"\n", MAC_ARG(pattrib->ra)));
#ifdef DBG_TX_DROP_FRAME
}
}
- if (psta == NULL) {
+ if (!psta) {
/* if we cannot get psta => drop the pkt */
DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_sta);
RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("\nupdate_attrib => get sta_info fail, ra:" MAC_FMT "\n", MAC_ARG(pattrib->ra)));
return _FAIL;
}
- if (psta == NULL) {
+ if (!psta) {
DBG_871X("%s, psta ==NUL\n", __func__);
return _FAIL;
}
return _FAIL;
}
*/
- if (pxmitframe->buf_addr == NULL) {
+ if (!pxmitframe->buf_addr) {
DBG_8192C("==> %s buf_addr == NULL\n", __func__);
return _FAIL;
}
tmp_buf = BIP_AAD = rtw_zmalloc(ori_len);
subtype = GetFrameSubType(pframe); /* bit(7)~bit(2) */
- if (BIP_AAD == NULL)
+ if (!BIP_AAD)
return _FAIL;
spin_lock_bh(&padapter->security_key_mutex);
else
psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
- if (psta == NULL) {
+ if (!psta) {
DBG_871X("%s, psta ==NUL\n", __func__);
goto xmitframe_coalesce_fail;
}
- if (!(psta->state & _FW_LINKED) || pxmitframe->buf_addr == NULL) {
+ if (!(psta->state & _FW_LINKED) || !pxmitframe->buf_addr) {
DBG_871X("%s, not _FW_LINKED or addr null\n", __func__);
goto xmitframe_coalesce_fail;
}
case AUTO_VCS:
default:
perp = rtw_get_ie(ie, _ERPINFO_IE_, &erp_len, ie_len);
- if (perp == NULL)
+ if (!perp)
pxmitpriv->vcs = NONE_VCS;
else {
protection = (*(perp + 2)) & BIT(1);
struct xmit_buf *pxmitbuf = NULL;
pxmitbuf = &pxmitpriv->pcmd_xmitbuf[buf_type];
- if (pxmitbuf != NULL) {
+ if (pxmitbuf) {
pxmitbuf->priv_data = NULL;
pxmitbuf->len = 0;
struct xmit_buf *pxmitbuf;
pcmdframe = rtw_alloc_xmitframe(pxmitpriv);
- if (pcmdframe == NULL) {
+ if (!pcmdframe) {
DBG_871X("%s, alloc xmitframe fail\n", __func__);
return NULL;
}
pxmitbuf = __rtw_alloc_cmd_xmitbuf(pxmitpriv, buf_type);
- if (pxmitbuf == NULL) {
+ if (!pxmitbuf) {
DBG_871X("%s, alloc xmitbuf fail\n", __func__);
rtw_free_xmitframe(pxmitpriv, pcmdframe);
return NULL;
list_del_init(&(pxmitbuf->list));
}
- if (pxmitbuf != NULL) {
+ if (pxmitbuf) {
pxmitpriv->free_xmit_extbuf_cnt--;
#ifdef DBG_XMIT_BUF_EXT
DBG_871X("DBG_XMIT_BUF_EXT ALLOC no =%d, free_xmit_extbuf_cnt =%d\n", pxmitbuf->no, pxmitpriv->free_xmit_extbuf_cnt);
_irqL irqL;
struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
- if (pxmitbuf == NULL)
+ if (!pxmitbuf)
return _FAIL;
spin_lock_irqsave(&pfree_queue->lock, irqL);
list_del_init(&(pxmitbuf->list));
}
- if (pxmitbuf != NULL) {
+ if (pxmitbuf) {
pxmitpriv->free_xmitbuf_cnt--;
#ifdef DBG_XMIT_BUF
DBG_871X("DBG_XMIT_BUF ALLOC no =%d, free_xmitbuf_cnt =%d\n", pxmitbuf->no, pxmitpriv->free_xmitbuf_cnt);
/* DBG_871X("+rtw_free_xmitbuf\n"); */
- if (pxmitbuf == NULL)
+ if (!pxmitbuf)
return _FAIL;
if (pxmitbuf->sctx) {
static void rtw_init_xmitframe(struct xmit_frame *pxframe)
{
- if (pxframe != NULL) { /* default value setting */
+ if (pxframe) { /* default value setting */
pxframe->buf_addr = NULL;
pxframe->pxmitbuf = NULL;
alloc_addr = rtw_zmalloc(sizeof(struct xmit_frame) + 4);
- if (alloc_addr == NULL)
+ if (!alloc_addr)
goto exit;
pxframe = (struct xmit_frame *)N_BYTE_ALIGMENT((SIZE_PTR)(alloc_addr), 4);
struct adapter *padapter = pxmitpriv->adapter;
_pkt *pndis_pkt = NULL;
- if (pxmitframe == NULL) {
+ if (!pxmitframe) {
RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("======rtw_free_xmitframe():pxmitframe == NULL!!!!!!!!!!\n"));
goto exit;
}
return _FAIL;
}
- if (psta == NULL) {
+ if (!psta) {
DBG_COUNTER(padapter->tx_logs.core_tx_enqueue_class_err_nosta);
res = _FAIL;
DBG_8192C("rtw_xmit_classifier: psta == NULL\n");
drop_cnt = 0;
}
- if (pxmitframe == NULL) {
+ if (!pxmitframe) {
drop_cnt++;
RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit: no more pxmitframe\n"));
DBG_COUNTER(padapter->tx_logs.core_tx_err_pxmitframe);
return false;
}
- if (psta == NULL) {
+ if (!psta) {
DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_nosta);
DBG_871X("%s, psta ==NUL\n", __func__);
return false;
/* DBG_871X("directly xmit pspoll_triggered packet\n"); */
/* pattrib->triggered = 0; */
- if (bmcst && xmitframe_hiq_filter(pxmitframe) == true)
+ if (bmcst && xmitframe_hiq_filter(pxmitframe))
pattrib->qsel = 0x11;/* HIQ */
return ret;
/* DBG_871X("enqueue, sq_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
- if (update_tim == true) {
+ if (update_tim) {
update_beacon(padapter, _TIM_IE_, NULL, true);
} else {
chk_bmc_sleepq_cmd(padapter);
/* DBG_871X("enqueue, sq_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
- if (update_tim == true)
+ if (update_tim)
/* DBG_871X("sleepq_len == 1, update BCNTIM\n"); */
/* upate BCN for TIM IE */
update_beacon(padapter, _TIM_IE_, NULL, true);
READ_NEXT_PAIR(v1, v2, i);
}
- if (bMatched == false) {
+ if (!bMatched) {
/* Condition isn't matched.
* Discard the following (offset, data) pairs.
*/
READ_NEXT_PAIR(v1, v2, i);
}
- if (bMatched == false) {
+ if (!bMatched) {
/* Condition isn't matched.
* Discard the following (offset, data) pairs.
*/
READ_NEXT_PAIR(v1, v2, i);
}
- if (bMatched == false) {
+ if (!bMatched) {
/* Condition isn't matched. Discard the following (offset, data) pairs. */
while (v1 < 0x40000000 && i < ArrayLen-2)
READ_NEXT_PAIR(v1, v2, i);
READ_NEXT_PAIR(v1, v2, i);
}
- if (bMatched == false) {
+ if (!bMatched) {
/* Condition isn't matched.
* Discard the following (offset, data) pairs.
*/
struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
PDM_ODM_T pDM_Odm = &pHalData->odmpriv;
- if (ODM_CheckPowerStatus(padapter) == false)
+ if (!ODM_CheckPowerStatus(padapter))
return;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Save ADDA parameters.\n"));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("ADDA ON.\n"));
pathOn = 0x01c00014;
- if (false == is2T) {
+ if (!is2T) {
pathOn = 0x01c00014;
PHY_SetBBReg(pDM_Odm->Adapter, ADDAReg[0], bMaskDWord, 0x01c00014);
} else {
u32 StartTime;
s32 ProgressingTime;
- if (ODM_CheckPowerStatus(padapter) == false)
+ if (!ODM_CheckPowerStatus(padapter))
return;
if (!(pDM_Odm->SupportAbility & ODM_RF_CALIBRATION))
if (0xFF == hw_channel_plan)
AutoLoadFail = true;
- if (false == AutoLoadFail) {
+ if (!AutoLoadFail) {
u8 hw_chnlPlan;
hw_chnlPlan = hw_channel_plan & (~EEPROM_CHANNEL_PLAN_BY_HW_MASK);
/* To Initi BT30 IGI */
pDM_DigTable->BT30_CurIGI = 0x32;
- if (pDM_Odm->BoardType & (ODM_BOARD_EXT_PA|ODM_BOARD_EXT_LNA)) {
- pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
- pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
- } else {
- pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
- pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
- }
+ pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
+ pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
}
bool bDFSBand = false;
bool bPerformance = true, bFirstTpTarget = false, bFirstCoverage = false;
- if (odm_DigAbort(pDM_Odm) == true)
+ if (odm_DigAbort(pDM_Odm))
return;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG() ===========================>\n\n"));
s32 err, ret;
u32 k = 0;
struct hw_xmit *hwxmits, *phwxmit;
- u8 no_res, idx, hwentry;
+ u8 idx, hwentry;
struct tx_servq *ptxservq;
struct list_head *sta_plist, *sta_phead, *frame_plist, *frame_phead;
struct xmit_frame *pxmitframe;
int inx[4];
err = 0;
- no_res = false;
hwxmits = pxmitpriv->hwxmits;
hwentry = pxmitpriv->hwxmit_entry;
ptxservq = NULL;
void rtl8723bs_free_xmit_priv(struct adapter *padapter)
{
- struct hal_com_data *phal;
struct xmit_priv *pxmitpriv;
struct xmit_buf *pxmitbuf;
struct __queue *pqueue;
struct list_head tmplist;
- phal = GET_HAL_DATA(padapter);
pxmitpriv = &padapter->xmitpriv;
pqueue = &pxmitpriv->pending_xmitbuf_queue;
phead = get_list_head(pqueue);
{
struct recv_buf *recvbuf;
struct dvobj_priv *sddev;
- struct sdio_data *psdio;
struct sdio_func *func;
u8 res = false;
void sta_info_update(struct adapter *padapter, struct sta_info *psta);
void ap_sta_info_defer_update(struct adapter *padapter, struct sta_info *psta);
u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta, bool active, u16 reason);
-int rtw_sta_flush(struct adapter *padapter);
+void rtw_sta_flush(struct adapter *padapter);
void start_ap_mode(struct adapter *padapter);
void stop_ap_mode(struct adapter *padapter);
}
check_need_indicate_scan_done:
- if (true == need_indicate_scan_done)
+ if (need_indicate_scan_done)
{
rtw_cfg80211_surveydone_event_callback(padapter);
rtw_cfg80211_indicate_scan_done(padapter, false);
cfg80211_del_sta(ndev, da, GFP_ATOMIC);
}
-static int rtw_cfg80211_monitor_if_open(struct net_device *ndev)
-{
- int ret = 0;
-
- DBG_8192C("%s\n", __func__);
-
- return ret;
-}
-
-static int rtw_cfg80211_monitor_if_close(struct net_device *ndev)
-{
- int ret = 0;
-
- DBG_8192C("%s\n", __func__);
- return ret;
-}
static netdev_tx_t rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struct net_device *ndev)
{
}
-static int rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)
-{
- int ret = 0;
- DBG_8192C("%s\n", __func__);
-
- return ret;
-}
static const struct net_device_ops rtw_cfg80211_monitor_if_ops = {
- .ndo_open = rtw_cfg80211_monitor_if_open,
- .ndo_stop = rtw_cfg80211_monitor_if_close,
- .ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
- .ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,
+ .ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
};
static int rtw_cfg80211_add_monitor_if (struct adapter *padapter, char *name, struct net_device **ndev)
flush_all_cam_entry(padapter); /* clear CAM */
- ret = rtw_sta_flush(padapter);
+ rtw_sta_flush(padapter);
- return ret;
+ return 0;
}
target_rate = target_rate/100000;
switch (target_rate) {
- case 10:
- ratevalue = 0;
- break;
- case 20:
- ratevalue = 1;
- break;
- case 55:
- ratevalue = 2;
- break;
- case 60:
- ratevalue = 3;
- break;
- case 90:
- ratevalue = 4;
- break;
- case 110:
- ratevalue = 5;
- break;
- case 120:
- ratevalue = 6;
- break;
- case 180:
- ratevalue = 7;
- break;
- case 240:
- ratevalue = 8;
- break;
- case 360:
- ratevalue = 9;
- break;
- case 480:
- ratevalue = 10;
- break;
- case 540:
- ratevalue = 11;
- break;
- default:
- ratevalue = 11;
- break;
+ case 10:
+ ratevalue = 0;
+ break;
+ case 20:
+ ratevalue = 1;
+ break;
+ case 55:
+ ratevalue = 2;
+ break;
+ case 60:
+ ratevalue = 3;
+ break;
+ case 90:
+ ratevalue = 4;
+ break;
+ case 110:
+ ratevalue = 5;
+ break;
+ case 120:
+ ratevalue = 6;
+ break;
+ case 180:
+ ratevalue = 7;
+ break;
+ case 240:
+ ratevalue = 8;
+ break;
+ case 360:
+ ratevalue = 9;
+ break;
+ case 480:
+ ratevalue = 10;
+ break;
+ case 540:
+ ratevalue = 11;
+ break;
+ default:
+ ratevalue = 11;
+ break;
}
set_rate:
sscanf(ptmp, "%d,%x", &bytes, &addr);
switch (bytes) {
- case 1:
- data32 = rtw_read8(padapter, addr);
- sprintf(extra, "0x%02X", data32);
- break;
- case 2:
- data32 = rtw_read16(padapter, addr);
- sprintf(extra, "0x%04X", data32);
- break;
- case 4:
- data32 = rtw_read32(padapter, addr);
- sprintf(extra, "0x%08X", data32);
- break;
- default:
- DBG_871X(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__);
- ret = -EINVAL;
- goto exit;
+ case 1:
+ data32 = rtw_read8(padapter, addr);
+ sprintf(extra, "0x%02X", data32);
+ break;
+ case 2:
+ data32 = rtw_read16(padapter, addr);
+ sprintf(extra, "0x%04X", data32);
+ break;
+ case 4:
+ data32 = rtw_read32(padapter, addr);
+ sprintf(extra, "0x%08X", data32);
+ break;
+ default:
+ DBG_871X(KERN_INFO "%s: usage> read [bytes],[address(hex)]\n", __func__);
+ ret = -EINVAL;
+ goto exit;
}
DBG_871X(KERN_INFO "%s: addr = 0x%08X data =%s\n", __func__, addr, extra);
sscanf(extra, "%d,%x,%x", &bytes, &addr, &data32);
switch (bytes) {
- case 1:
- rtw_write8(padapter, addr, (u8)data32);
- DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%02X\n", __func__, addr, (u8)data32);
- break;
- case 2:
- rtw_write16(padapter, addr, (u16)data32);
- DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%04X\n", __func__, addr, (u16)data32);
- break;
- case 4:
- rtw_write32(padapter, addr, data32);
- DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%08X\n", __func__, addr, data32);
- break;
- default:
- DBG_871X(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
- return -EINVAL;
+ case 1:
+ rtw_write8(padapter, addr, (u8)data32);
+ DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%02X\n", __func__, addr, (u8)data32);
+ break;
+ case 2:
+ rtw_write16(padapter, addr, (u16)data32);
+ DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%04X\n", __func__, addr, (u16)data32);
+ break;
+ case 4:
+ rtw_write32(padapter, addr, data32);
+ DBG_871X(KERN_INFO "%s: addr = 0x%08X data = 0x%08X\n", __func__, addr, data32);
+ break;
+ default:
+ DBG_871X(KERN_INFO "%s: usage> write [bytes],[address(hex)],[data(hex)]\n", __func__);
+ return -EINVAL;
}
return 0;
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- int ret = 0;
u8 major_cmd, minor_cmd;
u16 arg;
u32 extra_arg, *pdata, val32;
DBG_871X("enable driver ctrl ampdu density = %d\n", extra_arg);
- if ((extra_arg & 0x07) > 0x07)
+ if (extra_arg > 0x07)
padapter->driver_ampdu_spacing = 0xFF;
else
padapter->driver_ampdu_spacing = extra_arg;
}
- return ret;
+ return 0;
}
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
switch (command) {
- case IEEE_MLME_STA_DEAUTH:
+ case IEEE_MLME_STA_DEAUTH:
- if (!rtw_set_802_11_disassociate(padapter))
- ret = -1;
+ if (!rtw_set_802_11_disassociate(padapter))
+ ret = -1;
- break;
+ break;
- case IEEE_MLME_STA_DISASSOC:
+ case IEEE_MLME_STA_DISASSOC:
- if (!rtw_set_802_11_disassociate(padapter))
- ret = -1;
+ if (!rtw_set_802_11_disassociate(padapter))
+ ret = -1;
- break;
+ break;
- default:
- ret = -EOPNOTSUPP;
- break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
}
return ret;
}
-static int rtw_hostapd_sta_flush(struct net_device *dev)
+static void rtw_hostapd_sta_flush(struct net_device *dev)
{
/* _irqL irqL; */
/* struct list_head *phead, *plist; */
flush_all_cam_entry(padapter); /* clear CAM */
- return rtw_sta_flush(padapter);
-
+ rtw_sta_flush(padapter);
}
static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
/* DBG_871X("%s, cmd =%d\n", __func__, param->cmd); */
switch (param->cmd) {
- case RTL871X_HOSTAPD_FLUSH:
+ case RTL871X_HOSTAPD_FLUSH:
- ret = rtw_hostapd_sta_flush(dev);
+ rtw_hostapd_sta_flush(dev);
- break;
+ break;
- case RTL871X_HOSTAPD_ADD_STA:
+ case RTL871X_HOSTAPD_ADD_STA:
- ret = rtw_add_sta(dev, param);
+ ret = rtw_add_sta(dev, param);
- break;
+ break;
- case RTL871X_HOSTAPD_REMOVE_STA:
+ case RTL871X_HOSTAPD_REMOVE_STA:
- ret = rtw_del_sta(dev, param);
+ ret = rtw_del_sta(dev, param);
- break;
+ break;
- case RTL871X_HOSTAPD_SET_BEACON:
+ case RTL871X_HOSTAPD_SET_BEACON:
- ret = rtw_set_beacon(dev, param, p->length);
+ ret = rtw_set_beacon(dev, param, p->length);
- break;
+ break;
- case RTL871X_SET_ENCRYPTION:
+ case RTL871X_SET_ENCRYPTION:
- ret = rtw_set_encryption(dev, param, p->length);
+ ret = rtw_set_encryption(dev, param, p->length);
- break;
+ break;
- case RTL871X_HOSTAPD_GET_WPAIE_STA:
+ case RTL871X_HOSTAPD_GET_WPAIE_STA:
- ret = rtw_get_sta_wpaie(dev, param);
+ ret = rtw_get_sta_wpaie(dev, param);
- break;
+ break;
- case RTL871X_HOSTAPD_SET_WPS_BEACON:
+ case RTL871X_HOSTAPD_SET_WPS_BEACON:
- ret = rtw_set_wps_beacon(dev, param, p->length);
+ ret = rtw_set_wps_beacon(dev, param, p->length);
- break;
+ break;
- case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
+ case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
- ret = rtw_set_wps_probe_resp(dev, param, p->length);
+ ret = rtw_set_wps_probe_resp(dev, param, p->length);
- break;
+ break;
- case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
+ case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
- ret = rtw_set_wps_assoc_resp(dev, param, p->length);
+ ret = rtw_set_wps_assoc_resp(dev, param, p->length);
- break;
+ break;
- case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
+ case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
- ret = rtw_set_hidden_ssid(dev, param, p->length);
+ ret = rtw_set_hidden_ssid(dev, param, p->length);
- break;
+ break;
- case RTL871X_HOSTAPD_GET_INFO_STA:
+ case RTL871X_HOSTAPD_GET_INFO_STA:
- ret = rtw_ioctl_get_sta_data(dev, param, p->length);
+ ret = rtw_ioctl_get_sta_data(dev, param, p->length);
- break;
+ break;
- case RTL871X_HOSTAPD_SET_MACADDR_ACL:
+ case RTL871X_HOSTAPD_SET_MACADDR_ACL:
- ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
+ ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
- break;
+ break;
- case RTL871X_HOSTAPD_ACL_ADD_STA:
+ case RTL871X_HOSTAPD_ACL_ADD_STA:
- ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
+ ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
- break;
+ break;
- case RTL871X_HOSTAPD_ACL_REMOVE_STA:
+ case RTL871X_HOSTAPD_ACL_REMOVE_STA:
- ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
+ ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
- break;
+ break;
- default:
- DBG_871X("Unknown hostapd request: %d\n", param->cmd);
- ret = -EOPNOTSUPP;
- break;
+ default:
+ DBG_871X("Unknown hostapd request: %d\n", param->cmd);
+ ret = -EOPNOTSUPP;
+ break;
}
u8 *str;
switch (priv_args[k].set_args & IW_PRIV_TYPE_MASK) {
- case IW_PRIV_TYPE_BYTE:
- /* Fetch args */
- count = 0;
- do {
- str = strsep(&ptr, delim);
- if (NULL == str) break;
- sscanf(str, "%i", &temp);
- buffer[count++] = (u8)temp;
- } while (1);
- buffer_len = count;
-
- /* Number of args to fetch */
- wdata.data.length = count;
- if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
- wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
+ case IW_PRIV_TYPE_BYTE:
+ /* Fetch args */
+ count = 0;
+ do {
+ str = strsep(&ptr, delim);
+ if (NULL == str) break;
+ sscanf(str, "%i", &temp);
+ buffer[count++] = (u8)temp;
+ } while (1);
+ buffer_len = count;
+
+ /* Number of args to fetch */
+ wdata.data.length = count;
+ if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
+ wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
- break;
+ break;
- case IW_PRIV_TYPE_INT:
- /* Fetch args */
- count = 0;
- do {
- str = strsep(&ptr, delim);
- if (NULL == str) break;
- sscanf(str, "%i", &temp);
- ((s32*)buffer)[count++] = (s32)temp;
- } while (1);
- buffer_len = count * sizeof(s32);
-
- /* Number of args to fetch */
- wdata.data.length = count;
- if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
- wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
+ case IW_PRIV_TYPE_INT:
+ /* Fetch args */
+ count = 0;
+ do {
+ str = strsep(&ptr, delim);
+ if (NULL == str) break;
+ sscanf(str, "%i", &temp);
+ ((s32*)buffer)[count++] = (s32)temp;
+ } while (1);
+ buffer_len = count * sizeof(s32);
+
+ /* Number of args to fetch */
+ wdata.data.length = count;
+ if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
+ wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
- break;
+ break;
- case IW_PRIV_TYPE_CHAR:
- if (len > 0) {
- /* Size of the string to fetch */
- wdata.data.length = len;
- if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
- wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
+ case IW_PRIV_TYPE_CHAR:
+ if (len > 0) {
+ /* Size of the string to fetch */
+ wdata.data.length = len;
+ if (wdata.data.length > (priv_args[k].set_args & IW_PRIV_SIZE_MASK))
+ wdata.data.length = priv_args[k].set_args & IW_PRIV_SIZE_MASK;
- /* Fetch string */
- memcpy(buffer, ptr, wdata.data.length);
- } else {
- wdata.data.length = 1;
- buffer[0] = '\0';
- }
- buffer_len = wdata.data.length;
- break;
+ /* Fetch string */
+ memcpy(buffer, ptr, wdata.data.length);
+ } else {
+ wdata.data.length = 1;
+ buffer[0] = '\0';
+ }
+ buffer_len = wdata.data.length;
+ break;
- default:
- DBG_8192C("%s: Not yet implemented...\n", __func__);
- err = -1;
- goto exit;
+ default:
+ DBG_8192C("%s: Not yet implemented...\n", __func__);
+ err = -1;
+ goto exit;
}
if ((priv_args[k].set_args & IW_PRIV_SIZE_FIXED) &&
}
switch (priv_args[k].get_args & IW_PRIV_TYPE_MASK) {
- case IW_PRIV_TYPE_BYTE:
- /* Display args */
- for (j = 0; j < n; j++) {
- sprintf(str, "%d ", extra[j]);
- len = strlen(str);
- output_len = strlen(output);
- if ((output_len + len + 1) > 4096) {
- err = -E2BIG;
- goto exit;
- }
- memcpy(output+output_len, str, len);
+ case IW_PRIV_TYPE_BYTE:
+ /* Display args */
+ for (j = 0; j < n; j++) {
+ sprintf(str, "%d ", extra[j]);
+ len = strlen(str);
+ output_len = strlen(output);
+ if ((output_len + len + 1) > 4096) {
+ err = -E2BIG;
+ goto exit;
}
- break;
+ memcpy(output+output_len, str, len);
+ }
+ break;
- case IW_PRIV_TYPE_INT:
- /* Display args */
- for (j = 0; j < n; j++) {
- sprintf(str, "%d ", ((__s32*)extra)[j]);
- len = strlen(str);
- output_len = strlen(output);
- if ((output_len + len + 1) > 4096) {
- err = -E2BIG;
- goto exit;
- }
- memcpy(output+output_len, str, len);
+ case IW_PRIV_TYPE_INT:
+ /* Display args */
+ for (j = 0; j < n; j++) {
+ sprintf(str, "%d ", ((__s32*)extra)[j]);
+ len = strlen(str);
+ output_len = strlen(output);
+ if ((output_len + len + 1) > 4096) {
+ err = -E2BIG;
+ goto exit;
}
- break;
+ memcpy(output+output_len, str, len);
+ }
+ break;
- case IW_PRIV_TYPE_CHAR:
- /* Display args */
- memcpy(output, extra, n);
- break;
+ case IW_PRIV_TYPE_CHAR:
+ /* Display args */
+ memcpy(output, extra, n);
+ break;
- default:
- DBG_8192C("%s: Not yet implemented...\n", __func__);
- err = -1;
- goto exit;
+ default:
+ DBG_8192C("%s: Not yet implemented...\n", __func__);
+ err = -1;
+ goto exit;
}
output_len = strlen(output) + 1;
int ret = 0;
switch (cmd) {
- case RTL_IOCTL_WPA_SUPPLICANT:
- ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
- break;
- case RTL_IOCTL_HOSTAPD:
- ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
- break;
- case SIOCDEVPRIVATE:
- ret = rtw_ioctl_wext_private(dev, &wrq->u);
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
+ case RTL_IOCTL_WPA_SUPPLICANT:
+ ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
+ break;
+ case RTL_IOCTL_HOSTAPD:
+ ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
+ break;
+ case SIOCDEVPRIVATE:
+ ret = rtw_ioctl_wext_private(dev, &wrq->u);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
}
return ret;
padapter->intf_alloc_irq = &sdio_alloc_irq;
padapter->intf_free_irq = &sdio_free_irq;
- if (rtw_init_io_priv(padapter, sdio_set_intf_ops) == _FAIL)
- {
+ if (rtw_init_io_priv(padapter, sdio_set_intf_ops) == _FAIL) {
RT_TRACE(_module_hci_intfs_c_, _drv_err_,
("rtw_drv_init: Can't init io_priv\n"));
goto free_hal_data;
/* dev_alloc_name && register_netdev */
status = rtw_drv_register_netdev(if1);
- if (status != _SUCCESS) {
+ if (status != _SUCCESS)
goto free_if2;
- }
if (sdio_alloc_irq(dvobj) != _SUCCESS)
goto free_if2;
struct adapter *padapter = psdpriv->if1;
struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
- if (padapter->bDriverStopped == true)
- {
+ if (padapter->bDriverStopped == true) {
DBG_871X("%s bDriverStopped = %d\n", __func__, padapter->bDriverStopped);
return 0;
}
- if (pwrpriv->bInSuspend == true)
- {
+ if (pwrpriv->bInSuspend == true) {
DBG_871X("%s bInSuspend = %d\n", __func__, pwrpriv->bInSuspend);
pdbgpriv->dbg_suspend_error_cnt++;
return 0;
struct dvobj_priv *psdpriv = padapter->dvobj;
struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
- if (pwrpriv->bInSuspend == false)
- {
+ if (pwrpriv->bInSuspend == false) {
pdbgpriv->dbg_resume_error_cnt++;
DBG_871X("%s bInSuspend = %d\n", __func__, pwrpriv->bInSuspend);
return -1;
rtw_drv_proc_init();
ret = sdio_register_driver(&sdio_drvpriv.r871xs_drv);
- if (ret != 0)
- {
+ if (ret != 0) {
sdio_drvpriv.drv_registered = false;
rtw_drv_proc_deinit();
rtw_ndev_notifier_unregister();
return STATUS_SUCCESS;
}
-static inline int check_sd_speed_prior(u32 sd_speed_prior)
+static inline int valid_sd_speed_prior(u32 sd_speed_prior)
{
- bool fake_para = false;
+ bool valid_para = true;
int i;
for (i = 0; i < 4; i++) {
u8 tmp = (u8)(sd_speed_prior >> (i * 8));
if ((tmp < 0x01) || (tmp > 0x04)) {
- fake_para = true;
+ valid_para = false;
break;
}
}
- return !fake_para;
+ return valid_para;
}
-static inline int check_sd_current_prior(u32 sd_current_prior)
+static inline int valid_sd_current_prior(u32 sd_current_prior)
{
- bool fake_para = false;
+ bool valid_para = true;
int i;
for (i = 0; i < 4; i++) {
u8 tmp = (u8)(sd_current_prior >> (i * 8));
if (tmp > 0x03) {
- fake_para = true;
+ valid_para = false;
break;
}
}
- return !fake_para;
+ return valid_para;
}
static int rts5208_init(struct rtsx_chip *chip)
chip->rw_fail_cnt[i] = 0;
}
- if (!check_sd_speed_prior(chip->sd_speed_prior))
+ if (!valid_sd_speed_prior(chip->sd_speed_prior))
chip->sd_speed_prior = 0x01040203;
dev_dbg(rtsx_dev(chip), "sd_speed_prior = 0x%08x\n",
chip->sd_speed_prior);
- if (!check_sd_current_prior(chip->sd_current_prior))
+ if (!valid_sd_current_prior(chip->sd_current_prior))
chip->sd_current_prior = 0x00010203;
dev_dbg(rtsx_dev(chip), "sd_current_prior = 0x%08x\n",
#include <linux/serial.h> /* for rs_table, serial constants */
#include <linux/serial_reg.h> /* for more serial constants */
-#ifndef __sparc__
-#include <linux/serial.h>
-#endif
#include <linux/serial_core.h>
#include "spk_priv.h"
#
menuconfig UNISYSSPAR
bool "Unisys SPAR driver support"
- ---help---
- Support for the Unisys SPAR drivers
+ help
+ Support for the Unisys SPAR drivers
if UNISYSSPAR
skb_queue_head_init(&devdata->xmitbufhead);
/* create a cmdrsp we can use to post and unpost rcv buffers */
- devdata->cmdrsp_rcv = kmalloc(SIZEOF_CMDRSP, GFP_ATOMIC);
+ devdata->cmdrsp_rcv = kmalloc(SIZEOF_CMDRSP, GFP_KERNEL);
if (!devdata->cmdrsp_rcv) {
err = -ENOMEM;
goto cleanup_rcvbuf;
}
- devdata->xmit_cmdrsp = kmalloc(SIZEOF_CMDRSP, GFP_ATOMIC);
+ devdata->xmit_cmdrsp = kmalloc(SIZEOF_CMDRSP, GFP_KERNEL);
if (!devdata->xmit_cmdrsp) {
err = -ENOMEM;
goto cleanup_cmdrsp_rcv;
"%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n",
__func__, status, buf, length, mmal_flags, pts);
- if (status != 0) {
+ if (status) {
/* error in transfer */
if (buf) {
/* there was a buffer with the error so return it */
}
} else {
if (dev->capture.frame_count) {
- if (dev->capture.vc_start_timestamp != -1 &&
- pts != 0) {
+ if (dev->capture.vc_start_timestamp != -1 && pts) {
ktime_t timestamp;
s64 runtime_us = pts -
dev->capture.vc_start_timestamp;
struct v4l2_input *inp)
{
/* only a single camera input */
- if (inp->index != 0)
+ if (inp->index)
return -EINVAL;
inp->type = V4L2_INPUT_TYPE_CAMERA;
static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
- if (i != 0)
+ if (i)
return -EINVAL;
return 0;
}
ret = mmal_setup_components(dev, f);
- if (ret != 0) {
+ if (ret) {
v4l2_err(&dev->v4l2_dev,
"%s: failed to setup mmal components: %d\n",
__func__, ret);
static const s64 iso_qmenu[] = {
0, 100000, 200000, 400000, 800000,
};
-static const uint32_t iso_values[] = {
+
+static const u32 iso_values[] = {
0, 100, 200, 400, 800,
};
struct v4l2_ctrl *ctrl,
const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
{
- int ret = -EINVAL;
+ int ret;
struct vchiq_mmal_port *control;
control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
u32 port_handle; /* port */
u32 id; /* Parameter ID */
u32 size; /* Parameter size */
- uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
+ u32 value[MMAL_WORKER_PORT_PARAMETER_SPACE];
};
struct mmal_msg_port_parameter_set_reply {
u32 status; /* Status of mmal_port_parameter_get call */
u32 id; /* Parameter ID */
u32 size; /* Parameter size */
- uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
+ u32 value[MMAL_WORKER_PORT_PARAMETER_SPACE];
};
/* event messages */
(g_cache_line_size - 1)))) {
char *fragments;
- if (down_killable(&g_free_fragments_sema)) {
+ if (down_interruptible(&g_free_fragments_sema)) {
cleanup_pagelistinfo(pagelistinfo);
return NULL;
}
vchiq_log_trace(vchiq_core_log_level,
"%s(%p) called", __func__, instance);
- if (mutex_lock_killable(&state->mutex) != 0)
+ if (mutex_lock_killable(&state->mutex))
return VCHIQ_RETRY;
/* Remove all services */
vchiq_log_trace(vchiq_core_log_level,
"%s(%p) called", __func__, instance);
- if (mutex_lock_killable(&state->mutex) != 0) {
+ if (mutex_lock_killable(&state->mutex)) {
vchiq_log_trace(vchiq_core_log_level,
"%s: call to mutex_lock failed", __func__);
status = VCHIQ_RETRY;
vchiq_log_trace(vchiq_arm_log_level,
"%s - completion queue full", __func__);
DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT);
- if (wait_for_completion_killable(&instance->remove_event)) {
+ if (wait_for_completion_interruptible(
+ &instance->remove_event)) {
vchiq_log_info(vchiq_arm_log_level,
"service_callback interrupted");
return VCHIQ_RETRY;
}
DEBUG_TRACE(SERVICE_CALLBACK_LINE);
- if (wait_for_completion_killable(
- &user_service->remove_event)
- != 0) {
+ if (wait_for_completion_interruptible(
+ &user_service->remove_event)) {
vchiq_log_info(vchiq_arm_log_level,
"%s interrupted", __func__);
DEBUG_TRACE(SERVICE_CALLBACK_LINE);
break;
}
rc = mutex_lock_killable(&instance->state->mutex);
- if (rc != 0) {
+ if (rc) {
vchiq_log_error(vchiq_arm_log_level,
"vchiq: connect: could not lock mutex for "
"state %d: %d",
void *userdata;
int srvstate;
- if (copy_from_user
- (&args, (const void __user *)arg,
- sizeof(args)) != 0) {
+ if (copy_from_user(&args, (const void __user *)arg,
+ sizeof(args))) {
ret = -EFAULT;
break;
}
&(((struct vchiq_create_service __user *)
arg)->handle),
(const void *)&service->handle,
- sizeof(service->handle)) != 0) {
+ sizeof(service->handle))) {
ret = -EFAULT;
vchiq_remove_service(service->handle);
}
has been closed until the client library calls the
CLOSE_DELIVERED ioctl, signalling close_event. */
if (user_service->close_pending &&
- wait_for_completion_killable(
+ wait_for_completion_interruptible(
&user_service->close_event))
status = VCHIQ_RETRY;
break;
case VCHIQ_IOC_QUEUE_MESSAGE: {
struct vchiq_queue_message args;
- if (copy_from_user
- (&args, (const void __user *)arg,
- sizeof(args)) != 0) {
+ if (copy_from_user(&args, (const void __user *)arg,
+ sizeof(args))) {
ret = -EFAULT;
break;
}
(cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ?
VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE;
- if (copy_from_user
- (&args, (const void __user *)arg,
- sizeof(args)) != 0) {
+ if (copy_from_user(&args, (const void __user *)arg,
+ sizeof(args))) {
ret = -EFAULT;
break;
}
&(((struct vchiq_queue_bulk_transfer __user *)
arg)->mode),
(const void *)&mode_waiting,
- sizeof(mode_waiting)) != 0)
+ sizeof(mode_waiting)))
ret = -EFAULT;
}
} break;
}
if (copy_from_user(&args, (const void __user *)arg,
- sizeof(args)) != 0) {
+ sizeof(args))) {
ret = -EFAULT;
break;
}
DEBUG_TRACE(AWAIT_COMPLETION_LINE);
mutex_unlock(&instance->completion_mutex);
- rc = wait_for_completion_killable(
+ rc = wait_for_completion_interruptible(
&instance->insert_event);
mutex_lock(&instance->completion_mutex);
- if (rc != 0) {
+ if (rc) {
DEBUG_TRACE(AWAIT_COMPLETION_LINE);
vchiq_log_info(vchiq_arm_log_level,
"AWAIT_COMPLETION interrupted");
if (copy_from_user(&msgbuf,
(const void __user *)
&args.msgbufs[msgbufcount],
- sizeof(msgbuf)) != 0) {
+ sizeof(msgbuf))) {
if (ret == 0)
ret = -EFAULT;
break;
/* Copy the message to user space */
if (copy_to_user(msgbuf, header,
- msglen) != 0) {
+ msglen)) {
if (ret == 0)
ret = -EFAULT;
break;
(size_t)args.buf + ret *
sizeof(struct vchiq_completion_data)),
completion,
- sizeof(struct vchiq_completion_data))
- != 0) {
+ sizeof(struct vchiq_completion_data))) {
if (ret == 0)
ret = -EFAULT;
break;
&((struct vchiq_await_completion *)arg)
->msgbufcount,
&msgbufcount,
- sizeof(msgbufcount)) != 0) {
+ sizeof(msgbufcount))) {
ret = -EFAULT;
}
}
}
- if (ret != 0)
+ if (ret)
complete(&instance->remove_event);
mutex_unlock(&instance->completion_mutex);
DEBUG_TRACE(AWAIT_COMPLETION_LINE);
struct vchiq_header *header;
DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
- if (copy_from_user
- (&args, (const void __user *)arg,
- sizeof(args)) != 0) {
+ if (copy_from_user(&args, (const void __user *)arg,
+ sizeof(args))) {
ret = -EFAULT;
break;
}
do {
spin_unlock(&msg_queue_spinlock);
DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
- if (wait_for_completion_killable(
+ if (wait_for_completion_interruptible(
&user_service->insert_event)) {
vchiq_log_info(vchiq_arm_log_level,
"DEQUEUE_MESSAGE interrupted");
struct vchiq_config config;
if (copy_from_user(&args, (const void __user *)arg,
- sizeof(args)) != 0) {
+ sizeof(args))) {
ret = -EFAULT;
break;
}
case VCHIQ_IOC_SET_SERVICE_OPTION: {
struct vchiq_set_service_option args;
- if (copy_from_user(
- &args, (const void __user *)arg,
- sizeof(args)) != 0) {
+ if (copy_from_user(&args, (const void __user *)arg,
+ sizeof(args))) {
ret = -EFAULT;
break;
}
while (1) {
long rc = 0, uc = 0;
- if (wait_for_completion_killable(&arm_state->ka_evt)
- != 0) {
+ if (wait_for_completion_interruptible(&arm_state->ka_evt)) {
vchiq_log_error(vchiq_susp_log_level,
"%s interrupted", __func__);
flush_signals(current);
write_unlock_bh(&arm_state->susp_res_lock);
vchiq_log_info(vchiq_susp_log_level, "%s wait for previously "
"blocked clients", __func__);
- if (wait_for_completion_killable_timeout(
+ if (wait_for_completion_interruptible_timeout(
&arm_state->blocked_blocker, timeout_val)
<= 0) {
vchiq_log_error(vchiq_susp_log_level, "%s wait for "
write_unlock_bh(&arm_state->susp_res_lock);
vchiq_log_info(vchiq_susp_log_level, "%s wait for resume",
__func__);
- if (wait_for_completion_killable_timeout(
+ if (wait_for_completion_interruptible_timeout(
&arm_state->vc_resume_complete, timeout_val)
<= 0) {
vchiq_log_error(vchiq_susp_log_level, "%s wait for "
do {
write_unlock_bh(&arm_state->susp_res_lock);
- rc = wait_for_completion_killable_timeout(
+ rc = wait_for_completion_interruptible_timeout(
&arm_state->vc_suspend_complete,
msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS));
write_unlock_bh(&arm_state->susp_res_lock);
if (resume) {
- if (wait_for_completion_killable(
+ if (wait_for_completion_interruptible(
&arm_state->vc_resume_complete) < 0) {
vchiq_log_error(vchiq_susp_log_level,
"%s interrupted", __func__);
vchiq_log_info(vchiq_susp_log_level, "%s %s resume "
"blocked - waiting...", __func__, entity);
if (wait_for_completion_killable(
- &arm_state->resume_blocker) != 0) {
+ &arm_state->resume_blocker)) {
vchiq_log_error(vchiq_susp_log_level, "%s %s "
"wait for resume blocker interrupted",
__func__, entity);
vchiq_log_info(vchiq_susp_log_level, "%s %s wait for resume",
__func__, entity);
if (wait_for_completion_killable(
- &arm_state->vc_resume_complete) != 0) {
+ &arm_state->vc_resume_complete)) {
vchiq_log_error(vchiq_susp_log_level, "%s %s wait for "
"resume interrupted", __func__, entity);
ret = VCHIQ_ERROR;
platform_set_drvdata(pdev, drvdata);
err = vchiq_platform_init(pdev, &g_state);
- if (err != 0)
+ if (err)
goto failed_platform_init;
cdev_init(&vchiq_cdev, &vchiq_fops);
vchiq_cdev.owner = THIS_MODULE;
err = cdev_add(&vchiq_cdev, vchiq_devid, 1);
- if (err != 0) {
+ if (err) {
vchiq_log_error(vchiq_arm_log_level,
"Unable to register device");
goto failed_platform_init;
{
connected_init();
- if (mutex_lock_killable(&g_connected_mutex) != 0)
+ if (mutex_lock_killable(&g_connected_mutex))
return;
if (g_connected)
connected_init();
- if (mutex_lock_killable(&g_connected_mutex) != 0)
+ if (mutex_lock_killable(&g_connected_mutex))
return;
for (i = 0; i < g_num_deferred_callbacks; i++)
init_waitqueue_head(wq);
}
+/*
+ * All the event waiting routines in VCHIQ used a custom semaphore
+ * implementation that filtered most signals. This achieved a behaviour similar
+ * to the "killable" family of functions. While cleaning up this code all the
+ * routines where switched to the "interruptible" family of functions, as the
+ * former was deemed unjustified and the use "killable" set all VCHIQ's
+ * threads in D state.
+ */
static inline int
remote_event_wait(wait_queue_head_t *wq, struct remote_event *event)
{
if (!event->fired) {
event->armed = 1;
dsb(sy);
- if (wait_event_killable(*wq, event->fired)) {
+ if (wait_event_interruptible(*wq, event->fired)) {
event->armed = 0;
return 0;
}
remote_event_signal(&state->remote->trigger);
if (!is_blocking ||
- (wait_for_completion_killable(
+ (wait_for_completion_interruptible(
&state->slot_available_event)))
return NULL; /* No space available */
}
WARN_ON(!(stride <= VCHIQ_SLOT_SIZE));
if (!(flags & QMFLAGS_NO_MUTEX_LOCK) &&
- (mutex_lock_killable(&state->slot_mutex) != 0))
+ mutex_lock_killable(&state->slot_mutex))
return VCHIQ_RETRY;
if (type == VCHIQ_MSG_DATA) {
return VCHIQ_ERROR;
}
- WARN_ON((flags & (QMFLAGS_NO_MUTEX_LOCK |
- QMFLAGS_NO_MUTEX_UNLOCK)) != 0);
+ WARN_ON(flags & (QMFLAGS_NO_MUTEX_LOCK |
+ QMFLAGS_NO_MUTEX_UNLOCK));
if (service->closing) {
/* The service has been closed */
spin_unlock("a_spinlock);
mutex_unlock(&state->slot_mutex);
- if (wait_for_completion_killable(
+ if (wait_for_completion_interruptible(
&state->data_quota_event))
return VCHIQ_RETRY;
service_quota->slot_use_count);
VCHIQ_SERVICE_STATS_INC(service, quota_stalls);
mutex_unlock(&state->slot_mutex);
- if (wait_for_completion_killable(
+ if (wait_for_completion_interruptible(
&service_quota->quota_event))
return VCHIQ_RETRY;
if (service->closing)
return VCHIQ_ERROR;
- if (mutex_lock_killable(&state->slot_mutex) != 0)
+ if (mutex_lock_killable(&state->slot_mutex))
return VCHIQ_RETRY;
if (service->srvstate != VCHIQ_SRVSTATE_OPEN) {
/* The service has been closed */
header, size, VCHIQ_MSG_SRCPORT(msgid),
VCHIQ_MSG_DSTPORT(msgid));
- WARN_ON((flags & (QMFLAGS_NO_MUTEX_LOCK |
- QMFLAGS_NO_MUTEX_UNLOCK)) != 0);
+ WARN_ON(flags & (QMFLAGS_NO_MUTEX_LOCK |
+ QMFLAGS_NO_MUTEX_UNLOCK));
callback_result =
copy_message_data(copy_callback, context,
local = state->local;
- if ((VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_RESUME) &&
- (mutex_lock_killable(&state->sync_mutex) != 0))
+ if (VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_RESUME &&
+ mutex_lock_killable(&state->sync_mutex))
return VCHIQ_RETRY;
remote_event_wait(&state->sync_release_event, &local->sync_release);
QMFLAGS_IS_BLOCKING);
if (status == VCHIQ_SUCCESS) {
/* Wait for the ACK/NAK */
- if (wait_for_completion_killable(&service->remove_event)) {
+ if (wait_for_completion_interruptible(&service->remove_event)) {
status = VCHIQ_RETRY;
vchiq_release_service_internal(service);
} else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) &&
VCHIQ_STATUS_T status;
/* Abort any outstanding bulk transfers */
- if (mutex_lock_killable(&service->bulk_mutex) != 0)
+ if (mutex_lock_killable(&service->bulk_mutex))
return 0;
abort_outstanding_bulks(service, &service->bulk_tx);
abort_outstanding_bulks(service, &service->bulk_rx);
}
if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) {
- if (wait_for_completion_killable(&state->connect))
+ if (wait_for_completion_interruptible(&state->connect))
return VCHIQ_RETRY;
vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);
}
while (1) {
- if (wait_for_completion_killable(&service->remove_event)) {
+ if (wait_for_completion_interruptible(&service->remove_event)) {
status = VCHIQ_RETRY;
break;
}
request_poll(service->state, service, VCHIQ_POLL_REMOVE);
}
while (1) {
- if (wait_for_completion_killable(&service->remove_event)) {
+ if (wait_for_completion_interruptible(&service->remove_event)) {
status = VCHIQ_RETRY;
break;
}
queue = (dir == VCHIQ_BULK_TRANSMIT) ?
&service->bulk_tx : &service->bulk_rx;
- if (mutex_lock_killable(&service->bulk_mutex) != 0) {
+ if (mutex_lock_killable(&service->bulk_mutex)) {
status = VCHIQ_RETRY;
goto error_exit;
}
VCHIQ_SERVICE_STATS_INC(service, bulk_stalls);
do {
mutex_unlock(&service->bulk_mutex);
- if (wait_for_completion_killable(
+ if (wait_for_completion_interruptible(
&service->bulk_remove_event)) {
status = VCHIQ_RETRY;
goto error_exit;
}
- if (mutex_lock_killable(&service->bulk_mutex)
- != 0) {
+ if (mutex_lock_killable(&service->bulk_mutex)) {
status = VCHIQ_RETRY;
goto error_exit;
}
/* The slot mutex must be held when the service is being closed, so
claim it here to ensure that isn't happening */
- if (mutex_lock_killable(&state->slot_mutex) != 0) {
+ if (mutex_lock_killable(&state->slot_mutex)) {
status = VCHIQ_RETRY;
goto cancel_bulk_error_exit;
}
if (bulk_waiter) {
bulk_waiter->bulk = bulk;
- if (wait_for_completion_killable(&bulk_waiter->event))
+ if (wait_for_completion_interruptible(&bulk_waiter->event))
status = VCHIQ_RETRY;
else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED)
status = VCHIQ_ERROR;
if (count >= DEBUGFS_WRITE_BUF_SIZE)
count = DEBUGFS_WRITE_BUF_SIZE;
- if (copy_from_user(kbuf, buffer, count) != 0)
+ if (copy_from_user(kbuf, buffer, count))
return -EFAULT;
kbuf[count - 1] = 0;
VCHIQ_INSTANCE_T instance = f->private;
char firstchar;
- if (copy_from_user(&firstchar, buffer, 1) != 0)
+ if (copy_from_user(&firstchar, buffer, 1))
return -EFAULT;
switch (firstchar) {
return;
while (queue->write == queue->read + queue->size) {
- if (wait_for_completion_killable(&queue->pop))
+ if (wait_for_completion_interruptible(&queue->pop))
flush_signals(current);
}
struct vchiq_header *vchiu_queue_peek(struct vchiu_queue *queue)
{
while (queue->write == queue->read) {
- if (wait_for_completion_killable(&queue->push))
+ if (wait_for_completion_interruptible(&queue->push))
flush_signals(current);
}
struct vchiq_header *header;
while (queue->write == queue->read) {
- if (wait_for_completion_killable(&queue->push))
+ if (wait_for_completion_interruptible(&queue->push))
flush_signals(current);
}
config VT6655
tristate "VIA Technologies VT6655 support"
depends on PCI && MAC80211 && m
- ---help---
- This is a vendor-written driver for VIA VT6655.
-
+ help
+ This is a vendor-written driver for VIA VT6655.
tristate "VIA Technologies VT6656 support"
depends on MAC80211 && USB && WLAN && m
select FW_LOADER
- ---help---
- This is a vendor-written driver for VIA VT6656.
-
+ help
+ This is a vendor-written driver for VIA VT6656.
* Return Value: none
*
*/
-void vnt_set_antenna_mode(struct vnt_private *priv, u8 antenna_mode)
+int vnt_set_antenna_mode(struct vnt_private *priv, u8 antenna_mode)
{
switch (antenna_mode) {
case ANT_TXA:
break;
}
- vnt_control_out(priv, MESSAGE_TYPE_SET_ANTMD,
- (u16)antenna_mode, 0, 0, NULL);
+ return vnt_control_out(priv, MESSAGE_TYPE_SET_ANTMD,
+ (u16)antenna_mode, 0, 0, NULL);
}
/*
int vnt_vt3184_init(struct vnt_private *priv)
{
- int status;
+ int ret = 0;
u16 length;
u8 *addr;
u8 *agc;
u8 array[256];
u8 data;
- status = vnt_control_in(priv, MESSAGE_TYPE_READ, 0,
- MESSAGE_REQUEST_EEPROM, EEP_MAX_CONTEXT_SIZE,
- priv->eeprom);
- if (status != STATUS_SUCCESS)
- return false;
+ ret = vnt_control_in(priv, MESSAGE_TYPE_READ, 0, MESSAGE_REQUEST_EEPROM,
+ EEP_MAX_CONTEXT_SIZE, priv->eeprom);
+ if (ret)
+ goto end;
priv->rf_type = priv->eeprom[EEP_OFS_RFTYPE];
priv->bb_vga[3] = 0x0;
/* Fix VT3226 DFC system timing issue */
- vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL2,
- SOFTPWRCTL_RFLEOPT);
+ ret = vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL2,
+ SOFTPWRCTL_RFLEOPT);
+ if (ret)
+ goto end;
} else if (priv->rf_type == RF_VT3342A0) {
priv->bb_rx_conf = vnt_vt3184_vt3226d0[10];
length = sizeof(vnt_vt3184_vt3226d0);
priv->bb_vga[3] = 0x0;
/* Fix VT3226 DFC system timing issue */
- vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL2,
- SOFTPWRCTL_RFLEOPT);
+ ret = vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL2,
+ SOFTPWRCTL_RFLEOPT);
+ if (ret)
+ goto end;
} else {
- return true;
+ goto end;
}
memcpy(array, addr, length);
- vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
- MESSAGE_REQUEST_BBREG, length, array);
+ ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
+ MESSAGE_REQUEST_BBREG, length, array);
+ if (ret)
+ goto end;
memcpy(array, agc, length_agc);
- vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
- MESSAGE_REQUEST_BBAGC, length_agc, array);
+ ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
+ MESSAGE_REQUEST_BBAGC, length_agc, array);
+ if (ret)
+ goto end;
if ((priv->rf_type == RF_VT3226) ||
(priv->rf_type == RF_VT3342A0)) {
- vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG,
- MAC_REG_ITRTMSET, 0x23);
- vnt_mac_reg_bits_on(priv, MAC_REG_PAPEDELAY, 0x01);
+ ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG,
+ MAC_REG_ITRTMSET, 0x23);
+ if (ret)
+ goto end;
+
+ ret = vnt_mac_reg_bits_on(priv, MAC_REG_PAPEDELAY, 0x01);
+ if (ret)
+ goto end;
} else if (priv->rf_type == RF_VT3226D0) {
- vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG,
- MAC_REG_ITRTMSET, 0x11);
- vnt_mac_reg_bits_on(priv, MAC_REG_PAPEDELAY, 0x01);
+ ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG,
+ MAC_REG_ITRTMSET, 0x11);
+ if (ret)
+ goto end;
+
+ ret = vnt_mac_reg_bits_on(priv, MAC_REG_PAPEDELAY, 0x01);
+ if (ret)
+ goto end;
}
- vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x04, 0x7f);
- vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0x01);
+ ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x04, 0x7f);
+ if (ret)
+ goto end;
- vnt_rf_table_download(priv);
+ ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0x01);
+ if (ret)
+ goto end;
+
+ ret = vnt_rf_table_download(priv);
+ if (ret)
+ goto end;
/* Fix for TX USB resets from vendors driver */
- vnt_control_in(priv, MESSAGE_TYPE_READ, USB_REG4,
- MESSAGE_REQUEST_MEM, sizeof(data), &data);
+ ret = vnt_control_in(priv, MESSAGE_TYPE_READ, USB_REG4,
+ MESSAGE_REQUEST_MEM, sizeof(data), &data);
+ if (ret)
+ goto end;
data |= 0x2;
- vnt_control_out(priv, MESSAGE_TYPE_WRITE, USB_REG4,
- MESSAGE_REQUEST_MEM, sizeof(data), &data);
+ ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, USB_REG4,
+ MESSAGE_REQUEST_MEM, sizeof(data), &data);
- return true;
+end:
+ return ret;
}
/*
* Return Value: none
*
*/
-void vnt_set_short_slot_time(struct vnt_private *priv)
+int vnt_set_short_slot_time(struct vnt_private *priv)
{
+ int ret = 0;
u8 bb_vga = 0;
if (priv->short_slot_time)
else
priv->bb_rx_conf |= 0x20;
- vnt_control_in_u8(priv, MESSAGE_REQUEST_BBREG, 0xe7, &bb_vga);
+ ret = vnt_control_in_u8(priv, MESSAGE_REQUEST_BBREG, 0xe7, &bb_vga);
+ if (ret)
+ goto end;
if (bb_vga == priv->bb_vga[0])
priv->bb_rx_conf |= 0x20;
- vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0a, priv->bb_rx_conf);
+ ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0a,
+ priv->bb_rx_conf);
+
+end:
+ return ret;
}
void vnt_set_vga_gain_offset(struct vnt_private *priv, u8 data)
* Return Value: none
*
*/
-void vnt_set_deep_sleep(struct vnt_private *priv)
+int vnt_set_deep_sleep(struct vnt_private *priv)
{
- vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0c, 0x17);/* CR12 */
- vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0xB9);/* CR13 */
+ int ret = 0;
+
+ /* CR12 */
+ ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0c, 0x17);
+ if (ret)
+ return ret;
+
+ /* CR13 */
+ return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0xB9);
}
-void vnt_exit_deep_sleep(struct vnt_private *priv)
+int vnt_exit_deep_sleep(struct vnt_private *priv)
{
- vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0c, 0x00);/* CR12 */
- vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0x01);/* CR13 */
+ int ret = 0;
+
+ /* CR12 */
+ ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0c, 0x00);
+ if (ret)
+ return ret;
+
+ /* CR13 */
+ return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0x01);
}
void vnt_update_pre_ed_threshold(struct vnt_private *priv, int scanning)
void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length,
u16 tx_rate, u8 pkt_type, struct vnt_phy_field *phy);
-void vnt_set_short_slot_time(struct vnt_private *priv);
+int vnt_set_short_slot_time(struct vnt_private *priv);
void vnt_set_vga_gain_offset(struct vnt_private *priv, u8 data);
-void vnt_set_antenna_mode(struct vnt_private *priv, u8 antenna_mode);
+int vnt_set_antenna_mode(struct vnt_private *priv, u8 antenna_mode);
int vnt_vt3184_init(struct vnt_private *priv);
-void vnt_set_deep_sleep(struct vnt_private *priv);
-void vnt_exit_deep_sleep(struct vnt_private *priv);
+int vnt_set_deep_sleep(struct vnt_private *priv);
+int vnt_exit_deep_sleep(struct vnt_private *priv);
void vnt_update_pre_ed_threshold(struct vnt_private *priv, int scanning);
#endif /* __BASEBAND_H__ */
*/
int vnt_radio_power_off(struct vnt_private *priv)
{
- int ret = true;
+ int ret = 0;
switch (priv->rf_type) {
case RF_AL2230:
case RF_VT3226:
case RF_VT3226D0:
case RF_VT3342A0:
- vnt_mac_reg_bits_off(priv, MAC_REG_SOFTPWRCTL,
- (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3));
+ ret = vnt_mac_reg_bits_off(priv, MAC_REG_SOFTPWRCTL,
+ (SOFTPWRCTL_SWPE2 | SOFTPWRCTL_SWPE3));
break;
}
- vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_RXON);
+ if (ret)
+ goto end;
+
+ ret = vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_RXON);
+ if (ret)
+ goto end;
- vnt_set_deep_sleep(priv);
+ ret = vnt_set_deep_sleep(priv);
+ if (ret)
+ goto end;
- vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD);
+ ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD);
+end:
return ret;
}
{
struct device *dev = &priv->usb->dev;
const struct firmware *fw;
- int status;
void *buffer = NULL;
- bool result = false;
u16 length;
- int ii, rc;
+ int ii;
+ int ret = 0;
dev_dbg(dev, "---->Download firmware\n");
- rc = request_firmware(&fw, FIRMWARE_NAME, dev);
- if (rc) {
+ ret = request_firmware(&fw, FIRMWARE_NAME, dev);
+ if (ret) {
dev_err(dev, "firmware file %s request failed (%d)\n",
- FIRMWARE_NAME, rc);
- goto out;
+ FIRMWARE_NAME, ret);
+ goto end;
}
buffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
- if (!buffer)
+ 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);
- status = vnt_control_out(priv,
- 0,
- 0x1200 + ii,
- 0x0000,
- length,
- buffer);
+ ret = vnt_control_out(priv, 0, 0x1200 + ii, 0x0000, length,
+ buffer);
+ if (ret)
+ goto free_buffer;
dev_dbg(dev, "Download firmware...%d %zu\n", ii, fw->size);
-
- if (status != STATUS_SUCCESS)
- goto free_fw;
}
- result = true;
+free_buffer:
+ kfree(buffer);
free_fw:
release_firmware(fw);
-
-out:
- kfree(buffer);
-
- return result;
+end:
+ return ret;
}
MODULE_FIRMWARE(FIRMWARE_NAME);
int vnt_firmware_branch_to_sram(struct vnt_private *priv)
{
- int status;
-
dev_dbg(&priv->usb->dev, "---->Branch to Sram\n");
- status = vnt_control_out(priv,
- 1,
- 0x1200,
- 0x0000,
- 0,
- NULL);
- return status == STATUS_SUCCESS;
+ return vnt_control_out(priv, 1, 0x1200, 0x0000, 0, NULL);
}
int vnt_check_firmware_version(struct vnt_private *priv)
{
- int status;
-
- status = vnt_control_in(priv,
- MESSAGE_TYPE_READ,
- 0,
- MESSAGE_REQUEST_VERSION,
- 2,
- (u8 *)&priv->firmware_version);
+ int ret = 0;
+
+ ret = vnt_control_in(priv, MESSAGE_TYPE_READ, 0,
+ MESSAGE_REQUEST_VERSION, 2,
+ (u8 *)&priv->firmware_version);
+ if (ret) {
+ dev_dbg(&priv->usb->dev,
+ "Could not get firmware version: %d.\n", ret);
+ goto end;
+ }
dev_dbg(&priv->usb->dev, "Firmware Version [%04x]\n",
priv->firmware_version);
- if (status != STATUS_SUCCESS) {
- dev_dbg(&priv->usb->dev, "Firmware Invalid.\n");
- return false;
- }
if (priv->firmware_version == 0xFFFF) {
dev_dbg(&priv->usb->dev, "In Loader.\n");
- return false;
+ ret = -EINVAL;
+ goto end;
}
- dev_dbg(&priv->usb->dev, "Firmware Version [%04x]\n",
- priv->firmware_version);
-
if (priv->firmware_version < FIRMWARE_VERSION) {
/* branch to loader for download new firmware */
- vnt_firmware_branch_to_sram(priv);
- return false;
+ ret = vnt_firmware_branch_to_sram(priv);
+ if (ret) {
+ dev_dbg(&priv->usb->dev,
+ "Could not branch to SRAM: %d.\n", ret);
+ } else {
+ ret = -EINVAL;
+ }
}
- return true;
+
+end:
+ return ret;
}
{RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M}
};
-void vnt_int_start_interrupt(struct vnt_private *priv)
+int vnt_int_start_interrupt(struct vnt_private *priv)
{
+ int ret = 0;
unsigned long flags;
- int status;
dev_dbg(&priv->usb->dev, "---->Interrupt Polling Thread\n");
spin_lock_irqsave(&priv->lock, flags);
- status = vnt_start_interrupt_urb(priv);
+ ret = vnt_start_interrupt_urb(priv);
spin_unlock_irqrestore(&priv->lock, flags);
+
+ return ret;
}
static int vnt_int_report_rate(struct vnt_private *priv, u8 pkt_no, u8 tsr)
u8 sw[2];
} __packed;
-void vnt_int_start_interrupt(struct vnt_private *priv);
+int vnt_int_start_interrupt(struct vnt_private *priv);
void vnt_int_process_data(struct vnt_private *priv);
#endif /* __INT_H__ */
(u8 *)&set_key);
}
-void vnt_mac_reg_bits_off(struct vnt_private *priv, u8 reg_ofs, u8 bits)
+int vnt_mac_reg_bits_off(struct vnt_private *priv, u8 reg_ofs, u8 bits)
{
u8 data[2];
data[0] = 0;
data[1] = bits;
- vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK,
- reg_ofs, MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data),
- data);
+ return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, reg_ofs,
+ MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
}
-void vnt_mac_reg_bits_on(struct vnt_private *priv, u8 reg_ofs, u8 bits)
+int vnt_mac_reg_bits_on(struct vnt_private *priv, u8 reg_ofs, u8 bits)
{
u8 data[2];
data[0] = bits;
data[1] = bits;
- vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, reg_ofs,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
+ return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, reg_ofs,
+ MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
}
void vnt_mac_write_word(struct vnt_private *priv, u8 reg_ofs, u16 word)
MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
}
-void vnt_mac_set_led(struct vnt_private *priv, u8 state, u8 led)
+int vnt_mac_set_led(struct vnt_private *priv, u8 state, u8 led)
{
u8 data[2];
data[0] = led;
data[1] = state;
- vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_PAPEDELAY,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
+ return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_PAPEDELAY,
+ MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
}
void vnt_mac_disable_keyentry(struct vnt_private *priv, u8 entry_idx);
void vnt_mac_set_keyentry(struct vnt_private *priv, u16 key_ctl, u32 entry_idx,
u32 key_idx, u8 *addr, u8 *key);
-void vnt_mac_reg_bits_off(struct vnt_private *priv, u8 reg_ofs, u8 bits);
-void vnt_mac_reg_bits_on(struct vnt_private *priv, u8 reg_ofs, u8 bits);
+int vnt_mac_reg_bits_off(struct vnt_private *priv, u8 reg_ofs, u8 bits);
+int vnt_mac_reg_bits_on(struct vnt_private *priv, u8 reg_ofs, u8 bits);
void vnt_mac_write_word(struct vnt_private *priv, u8 reg_ofs, u16 word);
void vnt_mac_set_bssid_addr(struct vnt_private *priv, u8 *addr);
void vnt_mac_enable_protect_mode(struct vnt_private *priv);
void vnt_mac_enable_barker_preamble_mode(struct vnt_private *priv);
void vnt_mac_disable_barker_preamble_mode(struct vnt_private *priv);
void vnt_mac_set_beacon_interval(struct vnt_private *priv, u16 interval);
-void vnt_mac_set_led(struct vnt_private *privpriv, u8 state, u8 led);
+int vnt_mac_set_led(struct vnt_private *privpriv, u8 state, u8 led);
#endif /* __MAC_H__ */
*/
static int vnt_init_registers(struct vnt_private *priv)
{
+ int ret = 0;
struct vnt_cmd_card_init *init_cmd = &priv->init_command;
struct vnt_rsp_card_init *init_rsp = &priv->init_response;
u8 antenna;
int ii;
- int status = STATUS_SUCCESS;
u8 tmp;
u8 calib_tx_iq = 0, calib_tx_dc = 0, calib_rx_iq = 0;
dev_dbg(&priv->usb->dev, "---->INIbInitAdapter. [%d][%d]\n",
DEVICE_INIT_COLD, priv->packet_type);
- if (!vnt_check_firmware_version(priv)) {
- if (vnt_download_firmware(priv) == true) {
- if (vnt_firmware_branch_to_sram(priv) == false) {
- dev_dbg(&priv->usb->dev,
- " vnt_firmware_branch_to_sram fail\n");
- return false;
- }
- } else {
- dev_dbg(&priv->usb->dev, "FIRMWAREbDownload fail\n");
- return false;
+ ret = vnt_check_firmware_version(priv);
+ if (ret) {
+ ret = vnt_download_firmware(priv);
+ if (ret) {
+ dev_dbg(&priv->usb->dev,
+ "Could not download firmware: %d.\n", ret);
+ goto end;
+ }
+
+ ret = vnt_firmware_branch_to_sram(priv);
+ if (ret) {
+ dev_dbg(&priv->usb->dev,
+ "Could not branch to SRAM: %d.\n", ret);
+ goto end;
}
}
- if (!vnt_vt3184_init(priv)) {
+ ret = vnt_vt3184_init(priv);
+ if (ret) {
dev_dbg(&priv->usb->dev, "vnt_vt3184_init fail\n");
- return false;
+ goto end;
}
init_cmd->init_class = DEVICE_INIT_COLD;
init_cmd->long_retry_limit = priv->long_retry_limit;
/* issue card_init command to device */
- status = vnt_control_out(priv, MESSAGE_TYPE_CARDINIT, 0, 0,
- sizeof(struct vnt_cmd_card_init),
- (u8 *)init_cmd);
- if (status != STATUS_SUCCESS) {
+ ret = vnt_control_out(priv, MESSAGE_TYPE_CARDINIT, 0, 0,
+ sizeof(struct vnt_cmd_card_init),
+ (u8 *)init_cmd);
+ if (ret) {
dev_dbg(&priv->usb->dev, "Issue Card init fail\n");
- return false;
+ goto end;
}
- status = vnt_control_in(priv, MESSAGE_TYPE_INIT_RSP, 0, 0,
- sizeof(struct vnt_rsp_card_init),
- (u8 *)init_rsp);
- if (status != STATUS_SUCCESS) {
- dev_dbg(&priv->usb->dev,
- "Cardinit request in status fail!\n");
- return false;
+ ret = vnt_control_in(priv, MESSAGE_TYPE_INIT_RSP, 0, 0,
+ sizeof(struct vnt_rsp_card_init),
+ (u8 *)init_rsp);
+ if (ret) {
+ dev_dbg(&priv->usb->dev, "Cardinit request in status fail!\n");
+ goto end;
}
/* local ID for AES functions */
- status = vnt_control_in(priv, MESSAGE_TYPE_READ, MAC_REG_LOCALID,
- MESSAGE_REQUEST_MACREG, 1, &priv->local_id);
- if (status != STATUS_SUCCESS)
- return false;
+ ret = vnt_control_in(priv, MESSAGE_TYPE_READ, MAC_REG_LOCALID,
+ MESSAGE_REQUEST_MACREG, 1, &priv->local_id);
+ if (ret)
+ goto end;
/* do MACbSoftwareReset in MACvInitialize */
}
/* Set initial antenna mode */
- vnt_set_antenna_mode(priv, priv->rx_antenna_mode);
+ ret = vnt_set_antenna_mode(priv, priv->rx_antenna_mode);
+ if (ret)
+ goto end;
/* get Auto Fall Back type */
priv->auto_fb_ctrl = AUTO_FB_0;
/* CR255, enable TX/RX IQ and
* DC compensation mode
*/
- vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xff,
- 0x03);
+ ret = vnt_control_out_u8(priv,
+ MESSAGE_REQUEST_BBREG,
+ 0xff, 0x03);
+ if (ret)
+ goto end;
+
/* CR251, TX I/Q Imbalance Calibration */
- vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xfb,
- calib_tx_iq);
+ ret = vnt_control_out_u8(priv,
+ MESSAGE_REQUEST_BBREG,
+ 0xfb, calib_tx_iq);
+ if (ret)
+ goto end;
+
/* CR252, TX DC-Offset Calibration */
- vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xfC,
- calib_tx_dc);
+ ret = vnt_control_out_u8(priv,
+ MESSAGE_REQUEST_BBREG,
+ 0xfC, calib_tx_dc);
+ if (ret)
+ goto end;
+
/* CR253, RX I/Q Imbalance Calibration */
- vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xfd,
- calib_rx_iq);
+ ret = vnt_control_out_u8(priv,
+ MESSAGE_REQUEST_BBREG,
+ 0xfd, calib_rx_iq);
+ if (ret)
+ goto end;
} else {
/* CR255, turn off
* BB Calibration compensation
*/
- vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xff,
- 0x0);
+ ret = vnt_control_out_u8(priv,
+ MESSAGE_REQUEST_BBREG,
+ 0xff, 0x0);
+ if (ret)
+ goto end;
}
}
}
else
priv->short_slot_time = false;
- vnt_set_short_slot_time(priv);
+ ret = vnt_set_short_slot_time(priv);
+ if (ret)
+ goto end;
priv->radio_ctl = priv->eeprom[EEP_OFS_RADIOCTL];
if ((priv->radio_ctl & EEP_RADIOCTL_ENABLE) != 0) {
- status = vnt_control_in(priv, MESSAGE_TYPE_READ,
- MAC_REG_GPIOCTL1,
- MESSAGE_REQUEST_MACREG, 1, &tmp);
-
- if (status != STATUS_SUCCESS)
- return false;
+ ret = vnt_control_in(priv, MESSAGE_TYPE_READ,
+ MAC_REG_GPIOCTL1, MESSAGE_REQUEST_MACREG,
+ 1, &tmp);
+ if (ret)
+ goto end;
+
+ if ((tmp & GPIO3_DATA) == 0) {
+ ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1,
+ GPIO3_INTMD);
+ } else {
+ ret = vnt_mac_reg_bits_off(priv, MAC_REG_GPIOCTL1,
+ GPIO3_INTMD);
+ }
- if ((tmp & GPIO3_DATA) == 0)
- vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1,
- GPIO3_INTMD);
- else
- vnt_mac_reg_bits_off(priv, MAC_REG_GPIOCTL1,
- GPIO3_INTMD);
+ if (ret)
+ goto end;
}
- vnt_mac_set_led(priv, LEDSTS_TMLEN, 0x38);
- vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_SLOW);
+ ret = vnt_mac_set_led(priv, LEDSTS_TMLEN, 0x38);
+ if (ret)
+ goto end;
+
+ ret = vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_SLOW);
+ if (ret)
+ goto end;
- vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL0, 0x01);
+ ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL0, 0x01);
+ if (ret)
+ goto end;
- vnt_radio_power_on(priv);
+ ret = vnt_radio_power_on(priv);
+ if (ret)
+ goto end;
dev_dbg(&priv->usb->dev, "<----INIbInitAdapter Exit\n");
- return true;
+end:
+ return ret;
}
static void vnt_free_tx_bufs(struct vnt_private *priv)
for (ii = 0; ii < priv->num_tx_context; ii++) {
tx_context = priv->tx_context[ii];
+ if (!tx_context)
+ continue;
+
/* deallocate URBs */
if (tx_context->urb) {
usb_kill_urb(tx_context->urb);
kfree(priv->int_buf.data_buf);
}
-static bool vnt_alloc_bufs(struct vnt_private *priv)
+static int vnt_alloc_bufs(struct vnt_private *priv)
{
+ int ret = 0;
struct vnt_usb_send_context *tx_context;
struct vnt_rcb *rcb;
int ii;
for (ii = 0; ii < priv->num_tx_context; ii++) {
tx_context = kmalloc(sizeof(*tx_context), GFP_KERNEL);
- if (!tx_context)
+ if (!tx_context) {
+ ret = -ENOMEM;
goto free_tx;
+ }
priv->tx_context[ii] = tx_context;
tx_context->priv = priv;
/* allocate URBs */
tx_context->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!tx_context->urb)
+ if (!tx_context->urb) {
+ ret = -ENOMEM;
goto free_tx;
+ }
tx_context->in_use = false;
}
for (ii = 0; ii < priv->num_rcb; ii++) {
priv->rcb[ii] = kzalloc(sizeof(*priv->rcb[ii]), GFP_KERNEL);
- if (!priv->rcb[ii])
+ if (!priv->rcb[ii]) {
+ ret = -ENOMEM;
goto free_rx_tx;
+ }
rcb = priv->rcb[ii];
/* allocate URBs */
rcb->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!rcb->urb)
+ if (!rcb->urb) {
+ ret = -ENOMEM;
goto free_rx_tx;
+ }
rcb->skb = dev_alloc_skb(priv->rx_buf_sz);
- if (!rcb->skb)
+ if (!rcb->skb) {
+ ret = -ENOMEM;
goto free_rx_tx;
+ }
rcb->in_use = false;
/* submit rx urb */
- if (vnt_submit_rx_urb(priv, rcb))
+ ret = vnt_submit_rx_urb(priv, rcb);
+ if (ret)
goto free_rx_tx;
}
priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!priv->interrupt_urb)
+ if (!priv->interrupt_urb) {
+ ret = -ENOMEM;
goto free_rx_tx;
+ }
priv->int_buf.data_buf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL);
if (!priv->int_buf.data_buf) {
- usb_free_urb(priv->interrupt_urb);
- goto free_rx_tx;
+ ret = -ENOMEM;
+ goto free_rx_tx_urb;
}
- return true;
+ return 0;
+free_rx_tx_urb:
+ usb_free_urb(priv->interrupt_urb);
free_rx_tx:
vnt_free_rx_bufs(priv);
-
free_tx:
vnt_free_tx_bufs(priv);
-
- return false;
+ return ret;
}
static void vnt_tx_80211(struct ieee80211_hw *hw,
static int vnt_start(struct ieee80211_hw *hw)
{
+ int ret = 0;
struct vnt_private *priv = hw->priv;
priv->rx_buf_sz = MAX_TOTAL_SIZE_WITH_ALL_HEADERS;
- if (!vnt_alloc_bufs(priv)) {
+ ret = vnt_alloc_bufs(priv);
+ if (ret) {
dev_dbg(&priv->usb->dev, "vnt_alloc_bufs fail...\n");
- return -ENOMEM;
+ goto err;
}
clear_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags);
- if (vnt_init_registers(priv) == false) {
+ ret = vnt_init_registers(priv);
+ if (ret) {
dev_dbg(&priv->usb->dev, " init register fail\n");
goto free_all;
}
- if (vnt_key_init_table(priv))
+ ret = vnt_key_init_table(priv);
+ if (ret)
goto free_all;
priv->int_interval = 1; /* bInterval is set to 1 */
- vnt_int_start_interrupt(priv);
+ ret = vnt_int_start_interrupt(priv);
+ if (ret)
+ goto free_all;
ieee80211_wake_queues(hw);
usb_kill_urb(priv->interrupt_urb);
usb_free_urb(priv->interrupt_urb);
-
- return -ENOMEM;
+err:
+ return ret;
}
static void vnt_stop(struct ieee80211_hw *hw)
*dbm = -1 * (a + b * 2);
}
-void vnt_rf_table_download(struct vnt_private *priv)
+int vnt_rf_table_download(struct vnt_private *priv)
{
+ int ret = 0;
u16 length1 = 0, length2 = 0, length3 = 0;
u8 *addr1 = NULL, *addr2 = NULL, *addr3 = NULL;
u16 length, value;
/* Init Table */
memcpy(array, addr1, length1);
- vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
- MESSAGE_REQUEST_RF_INIT, length1, array);
+ ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
+ MESSAGE_REQUEST_RF_INIT, length1, array);
+ if (ret)
+ goto end;
/* Channel Table 0 */
value = 0;
memcpy(array, addr2, length);
- vnt_control_out(priv, MESSAGE_TYPE_WRITE,
- value, MESSAGE_REQUEST_RF_CH0, length, array);
+ ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, value,
+ MESSAGE_REQUEST_RF_CH0, length, array);
+ if (ret)
+ goto end;
length2 -= length;
value += length;
memcpy(array, addr3, length);
- vnt_control_out(priv, MESSAGE_TYPE_WRITE,
- value, MESSAGE_REQUEST_RF_CH1, length, array);
+ ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, value,
+ MESSAGE_REQUEST_RF_CH1, length, array);
+ if (ret)
+ goto end;
length3 -= length;
value += length;
memcpy(array, addr1, length1);
/* Init Table 2 */
- vnt_control_out(priv, MESSAGE_TYPE_WRITE,
- 0, MESSAGE_REQUEST_RF_INIT2, length1, array);
+ ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
+ MESSAGE_REQUEST_RF_INIT2, length1, array);
+ if (ret)
+ goto end;
/* Channel Table 0 */
value = 0;
memcpy(array, addr2, length);
- vnt_control_out(priv, MESSAGE_TYPE_WRITE,
- value, MESSAGE_REQUEST_RF_CH2,
- length, array);
+ ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, value,
+ MESSAGE_REQUEST_RF_CH2, length,
+ array);
+ if (ret)
+ goto end;
length2 -= length;
value += length;
addr2 += length;
}
}
+
+end:
+ return ret;
}
int vnt_rf_setpower(struct vnt_private *priv, u32 rate, u32 channel);
int vnt_rf_set_txpower(struct vnt_private *priv, u8 power, u32 rate);
void vnt_rf_rssi_to_dbm(struct vnt_private *priv, u8 rssi, long *dbm);
-void vnt_rf_table_download(struct vnt_private *priv);
+int vnt_rf_table_download(struct vnt_private *priv);
#endif /* __RF_H__ */
int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
u16 index, u16 length, u8 *buffer)
{
- int status = 0;
+ int ret = 0;
u8 *usb_buffer;
- if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
- return STATUS_FAILURE;
+ if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
+ ret = -EINVAL;
+ goto end;
+ }
mutex_lock(&priv->usb_lock);
usb_buffer = kmemdup(buffer, length, GFP_KERNEL);
if (!usb_buffer) {
- mutex_unlock(&priv->usb_lock);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto end_unlock;
}
- status = usb_control_msg(priv->usb,
- usb_sndctrlpipe(priv->usb, 0),
- request, 0x40, value,
- index, usb_buffer, length, USB_CTL_WAIT);
+ ret = usb_control_msg(priv->usb,
+ usb_sndctrlpipe(priv->usb, 0),
+ request, 0x40, value,
+ index, usb_buffer, length, USB_CTL_WAIT);
kfree(usb_buffer);
- mutex_unlock(&priv->usb_lock);
+ if (ret >= 0 && ret < (int)length)
+ ret = -EIO;
- if (status < (int)length)
- return STATUS_FAILURE;
-
- return STATUS_SUCCESS;
+end_unlock:
+ mutex_unlock(&priv->usb_lock);
+end:
+ return ret;
}
-void vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
+int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
{
- vnt_control_out(priv, MESSAGE_TYPE_WRITE,
- reg_off, reg, sizeof(u8), &data);
+ return vnt_control_out(priv, MESSAGE_TYPE_WRITE,
+ reg_off, reg, sizeof(u8), &data);
}
int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
u16 index, u16 length, u8 *buffer)
{
- int status;
+ int ret = 0;
u8 *usb_buffer;
- if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
- return STATUS_FAILURE;
+ if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
+ ret = -EINVAL;
+ goto end;
+ }
mutex_lock(&priv->usb_lock);
usb_buffer = kmalloc(length, GFP_KERNEL);
if (!usb_buffer) {
- mutex_unlock(&priv->usb_lock);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto end_unlock;
}
- status = usb_control_msg(priv->usb,
- usb_rcvctrlpipe(priv->usb, 0),
- request, 0xc0, value,
- index, usb_buffer, length, USB_CTL_WAIT);
+ ret = usb_control_msg(priv->usb,
+ usb_rcvctrlpipe(priv->usb, 0),
+ request, 0xc0, value,
+ index, usb_buffer, length, USB_CTL_WAIT);
- if (status == length)
+ if (ret == length)
memcpy(buffer, usb_buffer, length);
kfree(usb_buffer);
- mutex_unlock(&priv->usb_lock);
+ if (ret >= 0 && ret < (int)length)
+ ret = -EIO;
- if (status < (int)length)
- return STATUS_FAILURE;
-
- return STATUS_SUCCESS;
+end_unlock:
+ mutex_unlock(&priv->usb_lock);
+end:
+ return ret;
}
-void vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data)
+int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data)
{
- vnt_control_in(priv, MESSAGE_TYPE_READ,
- reg_off, reg, sizeof(u8), data);
+ return vnt_control_in(priv, MESSAGE_TYPE_READ,
+ reg_off, reg, sizeof(u8), data);
}
static void vnt_start_interrupt_urb_complete(struct urb *urb)
int vnt_start_interrupt_urb(struct vnt_private *priv)
{
- int status = STATUS_FAILURE;
+ int ret = 0;
- if (priv->int_buf.in_use)
- return STATUS_FAILURE;
+ if (priv->int_buf.in_use) {
+ ret = -EBUSY;
+ goto err;
+ }
priv->int_buf.in_use = true;
priv,
priv->int_interval);
- status = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
- if (status) {
- dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
- priv->int_buf.in_use = false;
+ ret = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
+ if (ret) {
+ dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", ret);
+ goto err_submit;
}
- return status;
+ return 0;
+
+err_submit:
+ priv->int_buf.in_use = false;
+err:
+ return ret;
}
static void vnt_submit_rx_urb_complete(struct urb *urb)
int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb)
{
- int status = 0;
+ int ret = 0;
struct urb *urb = rcb->urb;
if (!rcb->skb) {
dev_dbg(&priv->usb->dev, "rcb->skb is null\n");
- return status;
+ ret = -EINVAL;
+ goto end;
}
usb_fill_bulk_urb(urb,
vnt_submit_rx_urb_complete,
rcb);
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status) {
- dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", status);
- return STATUS_FAILURE;
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret) {
+ dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", ret);
+ goto end;
}
rcb->in_use = true;
- return status;
+end:
+ return ret;
}
static void vnt_tx_context_complete(struct urb *urb)
int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
u16 index, u16 length, u8 *buffer);
-void vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 ref_off, u8 data);
-void vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data);
+int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 ref_off, u8 data);
+int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data);
int vnt_start_interrupt_urb(struct vnt_private *priv);
int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb);
break;
if (pkt_offset & IS_MANAGMEMENT) {
- pkt_offset &= ~(IS_MANAGMEMENT |
- IS_MANAGMEMENT_CALLBACK |
- IS_MGMT_STATUS_SUCCES);
buff_ptr += HOST_HDR_OFFSET;
wilc_wfi_mgmt_rx(wilc, buff_ptr, pkt_len);
} else {
{
struct wlandevice *wlandev = dev->ml_priv;
- int err = 0;
- int result = 0;
-
- result = prism2_domibset_uint32(wlandev,
- DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID,
- key_index);
-
- if (result)
- err = -EFAULT;
-
- return err;
+ return prism2_domibset_uint32(wlandev,
+ DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID,
+ key_index);
}
static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,